What's differences between ItemView and View in marionette? - backbone.js

Version 2.x had many different kinds of views: View, ItemView,
LayoutView, CollectionView, CompositeView.
In version 3 ItemView, and LayoutView were ‘merged’ into View, and
CompositeView was deprecated for removal in v4. Now we have only View
and CollectionView.
What's differences between ItemView and View in marionette 2 ?
If I replace all my ItemView to View in my code in Marionette 3 ? How will I get problems ?

What's differences between ItemView and View in marionette 2 ?
Ok, in older version Marionette we created chosen instance view by use specific class name.
So. if you want create itemView you should use ItemView class, or if you want layout view instance you use LayoutView class. Each view class inherits from basic View class, so each views have common attributes, but not all.
Therefore ItemView is is a special case of View. In M2 create view's instance isn't recommended using direct by View class
In Marionette 3 you Don't have to indicate specific class because View class
is a more detailed. Depending on defined attributes your view can be a itemView or layoutView
var view = new Marionette.View({ template: "#some-template"});
//So we can say that is a normal itemView
var layoutView = new Marionette.View({
template: "#some-template",
regions: {
menu: "#menu",
content: "#content"
});
//So we can say that now is a layoutView, because we defined a regions.
Of course CollectionView has own class as in the previous version.
If I replace all my ItemView to View in my code in Marionette 3 ? How will I get problems ?
No, in this case you shouldn't have any problems.

Related

How to set data context where Views and View models in separate library

My Projects are
student.shell.client
student.views
student.viewModels
Modules.student
student.views has student.viewModels reference, in stuent.views used ViewModelLocator.AutoWireViewModel= true, its not resolving the view model. Is this is not a good practise to have views and view models in different project.
How to wireup views and view models here?
Yes, you can have your ViewModels in a separate assembly, you just have to tell the ViewModelLocator about the new rules to use to find them. In this blog you can see how to change the conventions to use your own convention:
http://brianlagunas.com/getting-started-prisms-new-viewmodellocator/
Very easy!
BTW #R. Richards, Prism uses DI when resolving the VMs automatically and all dependencies will be resolved with no issues and without injecting into the View ctor. This way, the View project will not have to even reference the ViewModel project. As long as all the assemblies are loaded into the AppDomain, it will just work.
Do you really need separate assemblies for the views and view models? Likely not. If you want to use the view model locator, then the easiest way is for them to be in the same project/assembly.
Either that, or new up the view models in the views code behind. This will work okay if your view models don't have any dependencies. Some frown on this because the coupling between the view and view model is rather tight.
public partial class StudentView : UserControl
{
public StudentView()
{
InitializeComponent();
DataContext = new StudentViewModel();
}
}
Or, you can have the IoC container provide the view model in the views contructor.
public partial class StudentView : UserControl
{
public StudentView(StudentViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
This second option (IoC) is a better option given the fact that your view models will likely have dependencies that the container can provide, too.
Hope this helps.

Marionette: setting collection after render doesn't update on model add

I have a nested composite view that checks its model for a collection, and if so sets that collection to itself as its collection.
onRender: ->
if model.attributes.has_collection
#collection = model.get 'myCollection'
This works quite well when the model has a collection, and the item view(s) all display, and when I add a new model to the collection, a new view appears.
However when there is no collection, and the button is clicked to create a new model, I need to create the model, set the collection (a collection of one) to the view's model, and get the view to display the model and any further models that are added. I have tried various things, right now I set the collection on the model and then run this function :
class List.myCompositeView
childView: myView
// *** //
setChildren: ->
#collection = #model.get 'myCollection'
#render()
The first model appears as it should, but further models that are created do not display. To repeat, they do appear when the collection is set in the onRender function. I realize there is lots of code that I did not add here, so if there is something (potentially) relevant to the problem that you need to know, let me know. Could it be that the view is not binding to the collection's events properly? Thanks!
A marionette collectionView has a private method called _initialEvents. When your collectionView is constructed it sets up this method to be called the first time the view is rendered. If your first render is when a collection view is not set then this would make sense that the events would not get wired up correctly. You should be able to call this private method after you set the collection and everything should work: #_initialEvents()
If it is helpful, this is the implementation of that method:
if (#collection) {
#listenTo(this.collection, 'add', #_onCollectionAdd);
#listenTo(this.collection, 'remove', #_onCollectionRemove);
#listenTo(this.collection, 'reset', #render);
if (#getOption('sort')) {
#listenTo(#collection, 'sort', #_sortViews);
}
}

Using common model for view

We have written a base Backbone view class which abstracts the common methods and properties. All our view class in a module extends this base class. Also this classes use same model.
The model contains a collection. I am listening to change event of collection. Whenever there change in collection i want to listen for change event to the corresponding view. Instead this event is getting triggered for all the model instances created.
Please share your inputs to resolve this issue.
in your base view, you can listen to model change events like this
intialize: function(options){
....... init code
this.model.on('change',this.modelChanged, this);
}
then in the modelChanged handler you can trigger a custom event on the view
modelChanged: function(){
this.trigger('modelChanged', [your args]);
}
then you can listen to the custom view event with 'on' function like we did with the model

Does backbone.js do any implicit associating a model with a view

Looking at some backbonejs examples on codeschoo.com, I don't see any explicit associations between views and their models. How does a view know what model it should be associated with? Is it by convention, e.g. TodoView assumes that this.model is of type Todo?
To explicitly set the model to the view, is it just a matter of passing in the model in the constructor?
If you pass a model property to a view constructor, it will set that directly as a property of the view instance, e.g. view.model. That's the case for a select group of other properties as well. Beyond those, properties passed to view constructors are set in view.options.
So yes, you can do this:
var view = new Backbone.View( {
model : new Backbone.Model
} );
Or change a an existing view instance's model any time by assigning to model:
view.model = new Backbone.Model;
Some people set references to views in models (e.g. model.view), but so far I've avoided that.
http://backbonejs.org/#View-constructor
When creating a new View, the options you pass are attached to the view as this.options...There are several special options that, if passed, will be attached directly to the view: model, collection, el, id, className, tagName and attributes.

Pass Single Instance of Model to Multiple View Models in same Module for different views

I am working on a project using PRISM where I have left navigation implemented as Tree View and any click event happens raise event using event aggergation to Enrolment Module which has multiple view model for multiple views (like Wizard Applicaiton where you can go through many views to collect data). I want to have a common or shared or singleton model which can be passed across this view models and save at the end.... users can click on any link any navigation at any time and it should save data in to this singleton model expsosed through different view model. Do you have any samples which are doing something like this... or can you type up a quick one on how to do it? OR it is not possible to do it at all. I am following all patterns from Brian Lagunas's Pluralsight Video for PRISM so try to use that way....
I would have a MasterViewModel which controls the "wizard" pages and current state
It would contain the following properties:
List<ViewModelBase> Pages
int CurrentPageIndex
ViewModelBase CurrentPage, which returns Pages[CurrentPageIndex]
MyClass DataObject
The MasterView that goes with the MasterViewModel would be nothing more than a ContentControl with it's Content bound to CurrentPage. I would probably also define DataTemplates in the MasterView which tells WPF which View to draw with which Page
Your MasterViewModel would be in charge of handling the pages, and passing each page a reference to the data it needs. For example in the constructor it might say,
public MasterViewModel(MyClass dataObject)
{
DataObject = dataObject;
Pages.Add(new InfoPage(DataObject));
Pages.Add(new AddressPage(DataObject.Addresses));
Pages.Add(new PhonePage(DataObject.Phones));
Pages.Add(new SaveMyClassPage(DataObject));
CurrentPageIndex = 0;
}
I have an example here if you're interested
I don't know, is it prism way, or something another, when I build something like wizard, first of all I create instance of all data which wizard collect.
public WizardData wd = new WizardData();
Then, every page of wizard are initialized by this wd instance, i.e.
public FirstWizardPage(WizardData wd)
{
this.wizardData = wd;
}
So, this way allow you to have button Finish on every page, for example. You can initialize your ViewModel with wd, or its properties.
This way is not the best. Its hust one of the possible way.
Another - is to create singleton and use it without reference passing from page-to-page.
When you use Prism you also have a Dependency Injection Container, usually Unity or MEF. To solve your problem you can register your model as singleton to those DI containers. Every view model that asks the DI container to resolve their dependecy, in our special case the model, will get the singleton instance back from the DI container.
Unity example: You register your model as singleton instance:
public void Initialize( )
{
container.RegisterInstance<Model>(new Model(), new ContainerControlledLifetimeManager( ));
}
Now you can resolve your dependencies in your view model:
public ViewModel(IUnityContainer container)
{
Model model = container.Resolve<Model>();
}

Resources