EmberJS: programmatically adding a child view to a collection view without changing underlying content - view

My EmberJS app is confusing me a lot at the moment. I have a collection view, that in turn defines an itemViewClass of a custom view I have defined in my code. Something like:
App.CarouselView = Ember.CollectionView.extend({
itemViewClass: App.SlideView.extend(),
});
And this CarouselView is rendered inside a template that has a dynamic segment backing it (I hope this makes sense?) . The controller for these dynamic segment is an array controller because the model for these dynamic segments is a collection :) (more confusion, please let me know)
App.SlidesController = Ember.ArrayController.extend();
By now all of you have figured that I am basically rendering a bunch of slides inside of a carousel. And these are dynamically backed in the collectionView by setting the property
contentBinding:'controller' // property set in CarouselView, controller corresponds to SlidesController
The confusion begins now. I want to add a slide to the existing set of slides. So I provide a button with an action : 'add' target='view'
In the SlidesView,
actions:{
add: function(){
var carouselView = this.get('childViews')[0];
// SlidesView has carouselView and another view as it's child, hence this.get('childViews')[0] is carouselView
var newCard = carouselView.createChildView(App.SlideView.extend());
carouselView.get('childViews').pushObject(newCard);
}
}
The above piece of code sucks and hurts me bad. I want to basically add a new SlideView to my CarouselView collection programmatically upon a button trigger. But apparently Ember recommends that childViews should not be manipulated directly and I ought to instead change the underlying content.
It states in my console.log that manipulating childViews is deprecated etc.
So essentially I need to add something to my content to my SlidesController content ? However, I don't want to add something to the content, this is just a soft add, that is providing the user with a slide so that he may choose to edit or add something if he wants to. He can always discard it. A hard add that will require me to persist the new slide to the DB will come once the user decides to save this information.

Related

How to make a laravel 5 view composer

I'm still learning Laravel and I'm working on a small project to help me understand better. In the project, I am in need of a global array, so that I may display it or its attributes on every view rendered. sort of on a notification bar, so that each page the user visits, he/she can see the number of notifications (which have been fetched in the background and are stored in the array).
I have done some research, and realized that I have to fetch and compile the array in a view composer I think. But everywhere I go, I cant seem to understand how to make a view composer.
I need to fetch the relevant rows from the database table, and make the resulting array available to each view rendered (I'm thinking attaching it somehow to my layouts/default.blade.php file.). Please help, any and all advice is greatly appreciated:)
You can now inject services on your view
More info here: https://laracasts.com/series/whats-new-in-laravel-5-1/episodes/2
You have to use Sub-Views of laravel blade. I guess your functionality is like a sidebar or like a top bar which will be rendered at every page.
//Your Controller pass data
class YOUR_CONTROLLER extends Controller {
public function index()
{
$data = YOUR_DATA;
return view('YOUR_VIEW_FILE', get_defined_vars());
}
}
//In Your View File
#extends('LAYOUTS_FILE')
#section('YOUR_SECTION')
#include('YOUR_SUB_VIEW_FOR_NOTIFICATION')//You need not pass any data passed all data will be available to this sub view.
#endsection
In your sub view
//Do what ever you want looping logic rendering HTML etc.
//In your layout file just yield or render the section that's it
#yield('YOUR_SECTION')
More explanation can be found Including Sub-Views

Ember.js and Isotope.js - Executing Javascript after all childviews became rendered

I use Ember.js (1.0. RC) and would like to apply Isotope.js's functionality to some of my views located in a "container".
So my route basically loads the models containing the needed data from a server, sets up the controller's content and binds it to the model's data, which works fine.
Next I declared a template for my IndexRoute which iterates over all the loaded items like this:
{{each item in this itemViewClass="App.ItemView"}}
The items are the images that should be filtered with isotope.js. ItemView only refers to a simple template for the time being.
The execution chain is the following: Route -> Fetching model data -> Set up controllers -> Create IndexView -> Pile up all the ItemViews in a DIV-container.
Now I need to check whether all the ItemViews are loaded and the rendering is finally finished to apply isotope.js's filtering functionality but I can't figure out how to do that.
The didInsertElement of the IndexView event fires as soon as it's been rendered and before the ItemViews were added to the DOM.
I already tried to set up a ContainerView which would work in conjunction with Ember.run.scheduleOnce("afterRender"...) if I didn't fetch the data through the models but hardcoded it to the content variable.
The CollectionView also did me no favor with this exercise.
Any ideas how to solve that misery? I'd really appreciate it. Thanks.
I am not sure how exactly isotope.js works..considering its just a jquery plugin, you can call isotope like this even if it is a ContainerView or CollectionView.
didInsertElement: function() {
Ember.run.next(this, function(){
this.$().isotope({}) // or watever code u want to write
});
}
This makes sure that the code inside ember.run runs once rendering is done completely..

Prism navigation- finding out origin of navigation request?

I have a viewmodel tied to a view used in a region. I'm trying to find a way that when that view is navigated to from a particular view (say view A), it does some work internally, like initializing some lists, setting some stuff, whatever. But if it has been navigated to from view B, it needs to NOT reinitialize everything, and just display the data it already has.
I could pass a parameter I suppose, saying whether this is a new operation or if we are going back to work on the old one, but I thought it would be nicer to be able to state that if we came from this view, we do one thing, and if we came from that one we do another.
If that makes sense :)
You can implement the INavigationAware interface which contains 3 methods. One of these methods is the OnNavigatedTo method. There you can access the journal and check the current entry. From there you should be able to determine if it came from View A or View B.
public void OnNavigatedTo(NavigationContext navigationContext)
{
var journal = navigationContext.NavigationService.Journal;
//use journal.CurrentEntry
}

Passing data from page to page

I'm looking for the best practice on how to pass data from page to page.
In Page A I have a button that fires off Page B.
On Page B I have 6 textboxes that allow the user to enter information.
When the user is done, the click on a button that brings them back to Page A.
I want to pass that data back to Page A.
I've seen suggestions to:
build XML documents and save to Isolated Storage
use the App class to store information in properties
pass it like a query string
I'm looking for the Best practice. Is there one that Microsoft recommends or one that is generally accepted as the best way?
Thanks
PhoneApplicationService.Current.State["yourparam"] = param
NavigationService.Navigate(new Uri("/view/Page.xaml", UriKind.Relative));
then in other page simply
var k = PhoneApplicationService.Current.State["yourparam"];
Personally I'd store the values entered on Page B in a model(object) that is also accessible to Page A.
Depending on how you're navigating to Page A the second time, one or more of the following may be usful to help understand passing values between pages:
How to pass the image value in one xaml page to another xaml page in windows phone 7?
Passing a complex object to a page while navigating in a WP7 Silverlight application
How to pass an object from a xaml page to another?
How to pass a value between Silverlight pages for WP7?
How do I navigate from one xaml page to another, and pass values?
One thing you can consider is to use MVC: let your App be the controller, store all data in the model, and the pages are just views that contains pure UI logic. In this case your pages are painters and you pass your model object around. This gives nice isolation of business logic and the UI so that you can rev them easily.
BTW, Silverlight and XAML are great tools for MVC so it's a natural match.
There's a couple of things at play here. First of all, if/when the user uses the Back button to return to page A instead of your button, is the information in the text boxes exchanged or not (is Back = Cancel, or is Back = OK?)
That said, if you're using NavigationService.GoBack (which you should be instead of NavigationService.Navigate, because if you use the Navigate call, repeated hits of the back key will cause all kinds of bad UX for your users), then QueryStrings are not an option. Because pages really have no way to reference each other in the WP7 Silverlight nav system, you need to use a 3rd party to hold your data. For that, you can turn to (a) Isolated Storage (slow & heavy, but fail-safe), (b) Use the PhoneApplicationService.State dictionary, or (c) use Global properties of some kind, either hung off of the application object, or using Statics/Singletons...
Remember to watch for Tombstoning behavior when you do this - your page will process the OnNavigatedTo method when (a) you navigate into it in your application (b) you navigate back to it when you complete your work on Page B, or (c) you tombstone your app from that page and return to your application using the Back key.
Sorry I didn't give a more direct answer there - a lot depends on your specific circumstances. In the most general case, I'd strongly consider using the App State Dictionary on the PhoneApplicationService...it is lightweight, easy to use, and survives tombstoning. Just be sure that your keys are as unique as they need to be.
If you create a new Windows Phone project and use the Windows Phone Databound Template you will have most of the work done for you.
What you will want to do is set up the ViewModel to contain all the data for your app. You can serialize and deserialize this data using IsolatedStorage so that it's saved across application sessions and when Tombstoning.
In the template you will notice MailViewModel and ItemViewModel. MainViewModel stores all the data your application needs including an ObservableCollection of ItemViewModel, and ItemViewModel represents the individual data type for your application.
On the DetailsPage.xaml page you'll want to DataBind each textbox to the App.MainViewModel Items. Set the binding to TwoWay if you want the ViewModel to get updated as soon as the user manipulates the data on DetailsPage.xaml. You can optionally set the Binding to OneWay and then have an OK button that writes the changes back to the ViewModel and saves to IsolatedStorage.
Here is an example of what a Binding looks like:
<TextBlock x:Name="ListTitle" Text="{Binding LineOne}" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
In this case LineOne is a property in ItemViewModel and the page gets this data from the query string when the user selects an item from the MainPage.xaml. The DataContext for the page determs where the databound information comes from.
Here is the snippet where the MainPage passes the selected item from the ViewModel to the DetailsPage.
// Handle selection changed on ListBox
private void MainListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// If selected index is -1 (no selection) do nothing
if (MainListBox.SelectedIndex == -1)
return;
// Navigate to the new page
NavigationService.Navigate(new Uri("/DetailsPage.xaml?selectedItem=" + MainListBox.SelectedIndex, UriKind.Relative));
// Reset selected index to -1 (no selection)
MainListBox.SelectedIndex = -1;
}
Here is how the DetailsPage gets the selected item.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
string selectedIndex = "";
if (NavigationContext.QueryString.TryGetValue("selectedItem", out selectedIndex))
{
int index = int.Parse(selectedIndex);
DataContext = App.ViewModel.Items[index];
}
}
Play around with the default template above and ask any additional questions.
The beauty of databinding and the ObservableCollection is that you can just update the data and the UX will reflect those changes immediatley. This is because any changes to the data fires off an event:
public string LineOne
{
get
{
return _lineOne;
}
set
{
if (value != _lineOne)
{
_lineOne = value;
NotifyPropertyChanged("LineOne");
}
}
}
NotifyPropertyChanged() that broadcasts this information to the View.
You can also keep it simple and use PhoneApplicationService.Current.State which is basically a hashtable. You will need to implement your own marshalling to and from isolated storage if you want anything to outlive the app.
Omar's suggestion to use the Windows Phone Databound Template is probably the best idea on this page. It amounts to the same as my suggestion but you will get a better result (more maintainable code) at the cost of a longer steeper learning curve.
I suggest you do it my way and then do it again Omar's way.
as i implemented like this.. Whether its correct or not i dont know..
When u click news list page it should open the news detail page.
I want to pass the selected news item contents from news List-Page to news-details Page.
the News list page contains following method.
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
NewsDetailsPage newsDetailPage = (e.Content as NewsDetailsPage);
if (newsDetailPage != null)
newsDetailPage.SelectedNewsItem = SelectedNewsItem; //Contains the news details
base.OnNavigatedFrom(e);
}
In the News details Page. U can access that(SelectedNewsItem) object.
This may or may not be correct.
One option is to use Application.Resources:
Store data:
Application.Current.Resources.Add("NavigationParam", customers);
NavigationService.Navigate(new Uri("/Page2.xaml", UriKind.Relative));
Retrieve data:
var customers = (List<Customer>) Application.Current.Resources["NavigationParam"];
Here's a blog post with describes this in more detail: http://mikaelkoskinen.net/windows-phone-pass-data-between-pages-application-resources/ (author: me)

prism switch between views in the same region

I have a region named "ActiveModule" and want to re-use it with different views, for example you press the search button and I show the search view in there, etc. etc.
The only way I can ATM do that is to deactivate all the active views in that region and then activate the view I like, this is a bit dirty, is there a "viewManager" or something similar I can use?
If your region is a ContentControl or derives from ContentControl, then there can only be one active view at a time, and you only need to activate the search view on the region.
Did you consider to use a type of contentControl that is able to show multiple views?
For example you can use a TabControl like this:
<TabControl Name="MainRegion" Regions:RegionManager.RegionName="MainRegion"/>
You can now add more than one view to the region. Use INavigationAware and IActiveAware interfaces from Prism to be able to do navigation on the views (activate them, find the correct view etc.).
If you are using a IRegionManager, you can remove all of the views whose types you recognize and then add your own.
foreach (var view in _regionsManager.Regions["MyRegion"].Views.ToArray())
{
if (view is MyType ||
view is MyOtherType)
_regionsManager.Regions["MyRegion"].Remove(view);
}
_regionsManager.AddToRegion("MyRegion", typeof(MyView));
Its by no means ideal, but it works. :)
To my knowledge what you are doing is the only way, theoretically in SCSF the top most view was activated by the framework. You could create ur own ViewManager or a ShowViewService equivalent to get this done. MAtter of fact, thats what i have done!
Not sure how you laid out your framework but if you are using navigation related framework you can simply call
regionManager.RequestNavigate(RegionNames.MainContentRegion, new Uri("your target view" + parameters, UriKind.Relative));
the above line will take care of deactivating other views in the region.
Otherwise if you do view discovery or view injection you can use the approach here
region.Activate(view);

Resources