I am just starting out with backbone and am trying to set up a view which has a question list. To the left of the list I have four filters, to filter the list by language, country, status, and study. The list and each of the filters are loaded into their own collections.
My idea was to make this one view with multiple collections, but I wonder if this is best practice in backbone since all the examples I have seen only have one collection per view.
Another idea was to break in into two views with one being responsible for the filters and then a child view being responsible only for the list of questions.
Or, is it more backbone style to drop all of the collections into a model and then pass that model to my view like it mentions here: http://documentcloud.github.com/backbone/#FAQ-nested
Thanks for your ideas.
Yes. Theoretically a view can encompass any number of inner objects/collections. It generally makes good sense to have views be as discrete as possible, but there could be reasons to wrap more than one thing in a single view.
This is all a matter of design. I don't see what creating a container model as a bucket for your collections buys you.
Don't be too concerned with the absolute best way. Sometimes it takes walking a little down the wrong path to figure out the better ways for your particular project.
I think it's completely legit to pass more than one model or collection to a view - when appropriate.
Passing a model or collection to a view constructor will automatically appended that object to the view instance (so it's in this.model or this.collection) but you can also pass other data such as extra collections and they will be located in the options object (accessible from within your view as this.options.countries, etc.). Your views initialize method, if it exists, will also be passed this object.
Not sure of best practices but if you can break it into views then its good. Otherwise you'll be better off creating a view model with multiple collections in it and use them in the view.
Related
I'm getting started with angular2 and wanted to create a todo-list web app. The UI should consist of two pages (=components) which get slide in/out via JavaScript.
The first one shows all todos in a vertical list and the other one shows additional details when a todo item from the list is clicked.
I'm now asking myself, what's the right way in angular2 to declare the page components?
Should I build a generic component like this?
<page type="list"></page>
<page type="detail"></page>
Or should I create a new component for each page?
<listpage></listpage>
<detailpage></detailpage>
In general, without knowing more details, my gut sense would be that the latter would be more appropriate, i.e. create a new component for each page.
You require two fundamentally distinct types of entities:
a collection and
a single item from that collection.
The first solution that you propose, i.e. a generic component, would be more suitable to multiple entities that all share some basic underlying structure but differ in some (but not all) details, e.g., two different collection views that both list all items but format those items in two different ways. To force that strategy onto your use case would require your generic page component to have no universally shared structure: what template or logic would you share between a todo-list collection and a single todo-item from that collection? Everything would depend on the value of the type attribute. Then what meaning would page have? Essentially nothing.
Your latter suggestion, i.e. having two distinct components for these two different entities, seems more in the true spirit of how angular components are meant to be used.
I suppose one could argue that a more generic page component/view could have some valuable structure that persists for both the list view and the detail view, e.g. main title, navigation links, user info, etc. However, even if you implemented that, I think you'd want to eventually create separate (more deeply nested?) components for the whole list versus for an individual item, which eventually comes back around to implementing your latter suggestion.
I think a useful model is the example code provided on the official Angular2 web site. I could point to several different examples, but I think the clearest parallel to your situation is in the "Advanced Documentation" section, under the "Routing & Navigation" heading. There they provide code that separates components as follows:
hero-list.component: This would seem to parallel your listpage.
hero-detail.component: This would seem to parallel your detailpage.
Clearly they've separated out these two parts of the app into distinct components.
This sort of strategy decision may also depend on the size/complexity of your "entities". If your "list" and "detail" views were both extremely simple, I suppose you could distinguish between them within a single component (e.g. page), just using an attribute (e.g. type). However, in a todo app, I can't imagine either a list view or a detail view being extremely simple. Thus trying to squash both into a single page component would make the component too complex.
Yes I know there is a plugin called Backbone-Relational but I have a serious problem with its fetchRelated function which, in my opinion, renders it useless for me.
So I was wondering if there are any alternatives? Or do we even need plugins like Backbone-Relational at all? How would you handle following scenario with pure Backbone:
Let's say we have two Backbone models: Company and Person. A Company instance can have many Persons. So company.get('employees') will return an array of Person IDs. If I want to get details of related employees, I'll have to iterate over the array and fetch() each of the Persons from server. But what if those Person instances have been already downloaded? Is there a clean way to make sure that there is no redundancy?
May be we can maintain a Collection for each model and dump every instance we download into it. Then we can download an instance only when it is not present in the Collection. But I think it will make code look horrible.
So please share your experience guys. Thanks!
As you suggested, I would give my Company model a Persons attribute. But you seem to forget collections also have a fetch method (as well as many other methods you'd find pretty useful, as the get method).
Also, as a last thing, I'd like to quote Backbone's doc (regarding the fetch method of Collections):
"Note that fetch should not be used to populate collections on page load — all models needed at load time should already be bootstrapped in to place. fetch is intended for lazily-loading models for interfaces that are not needed immediately: for example, documents with collections of notes that may be toggled open and closed."
Sorry if the question is vague but I am really having trouble finding information on this. I come from the Flex/ActionScript world where, for the most part, we have very simple Value Objects (VOs) to represent things like a User or an Address and we have Models that usually represented collections of those VOs along with business logic. There were some frameworks that would include a view model, MVVM. I know that there is no "right way" to do these things but I can't seem to point my finger on the basics.
Are all Backbone views supposed to have their own models? Given that I will likely not have a view called "User", would I also include domain models?
Would folders look something like this?
App
models
domain
User
Address
view
UserProfileModel
views
UserProfileView
collections
Users
Again, sorry if this doesn't make sense or is too general. I am just trying to get an idea of how far along the JS world has gotten in terms of MVC patterns. Thanks.
I don't think there is an only-one answer here. Every case will have an answer.
Are all Backbone views supposed to have their own models?
No.
There will be Views that will make reference to a Model, other ones will be making reference to a Collection. There will be also Views making reference to multiple Models, and others those will make reference to no-Model at all.
A View is an User Interface. It shows data to the User and listen to the events the User trigger on this data representation.
For example, if I have a Model called Friend and I want to create an interface to list a bunch of this Models I'll have:
FriendsView: which is a View that represents a Collection of Friends.
FriendView: which is a sub-View of FriendsView wich represent only one Friend. It can also listen to the click on the destroy button for this Friend.
But also I'll want to have a form to search from Friends in my server:
FriendSearchView: which not have reference to any Model or Collection. But is listening to the User filling an input field.
Would I also include domain models?
I don't know what do you mean with domain models but if you are asking about where to put the business logic Backbone is very agnostic about that. I recommend to put as much calculation as possible into the Models or Collections. Also you can use your own pure JS Util library.
Keep the Views clean. Only responding to User events and calling Model and Collection methods as needed. Also listening in changes in the Model or Collection from which it is showing the data.
How folders should look like?
Well, Backbone is again agnostic about this. There are a lot of literature about this.
My projects use to be small, less than 30 files. I put all of them in the same folder with a naming convection like this:
Friend
Friends
FriendView
FriednsView
I'm trying to implement a MVVM based Single Page Application and currently am using the framework Knockout.js to handle the viewmodel/view portion of MVVM. I'm confused though, as every example I've looked at for implementing Knockout involves saving an entire viewmodel to the database. Aren't these examples missing a "model" step, where the viewmodel syncs with the data-layer model and the model does validation / Server synchronization.
I would like to have multiple different templates/views on the single page each with a different viewmodel. Another thing that I find is missing with knockout.js is synchronizing a single model (not viewmodel) across different views. I don't think it makes sense to have one giant viewmodel that every view shares, so I was thinking that each view would have its own viewmodel but each viewmodel would sync with the fields of just a few application-wide models that are needed for each view.
The page I'm working on fetches a giant model (30+ fields, multiple layers of parent/child relationships) and I think it makes sense to just have all of my viewmodels sync with this model. I have investigated Knockback.js (which combines knockout.js and backbone.js) however I ended up re-writing the majority of the functions such as fetch, set, save, because the page is getting data from an API (and I can't just sync an entire model back and forth with the server) so I decided against it.
visual example of my application:
(model layer)
M | M
(viewmodel/view layer) VM-V | VM-V | VM-V | VM-V
another example
An example model would be User = {firstName: "first", lastName: "last", ... }
one viewmodel only needs first name, another viewmodel only needs last name
ViewModelA={firstName: app.User.firstName()}ViewModelB={firstName: app.User.lastName()}
Is the only way to do this to define a pub/sub system for Model and Viewmodel changes? Is this even good/maintainable architecture? Am I missing a basic concept here? All advice welcome.
If I read this correctly, there's a lot of questions in here all focused on how to build a MVVM / SPA with Knockout. There are a few things to tackle, as you pointed out. One is how to communicate between viewmodel/view pairs.
Master ViewModel
One way to do that is to have a master viewmodel as the answer from #Tyrsius. Your shell could have a viewmodel that binds more available data. The master viewmodel could orchestrate the child view models, too. If you go this route then you have to be careful to bind the outer shell to the master viewmodel and the inner ones to specific HTML elements in the DOM. The master viewmodel could facilitate the communication between them if need be.
Decoupled View/ViewModel Pairs
Another option is to use viewmodel/view pairs and no master viewmodel. Each view is loaded into a region of the DOM and bound on its own. They act as separate units and are decoupled from one another. You could use pub/sub to then talk between the, but if all you need is a way for the data to be synched through observables, Knockout provides many options. The one I like is to have each viewmodel surface model objects. So a view has a viewmodel which surfaces data (from a model) that is specific for the view. So many viewmodels may surface the same model in different ways. So when a view updates a viewmodel property (that is in a model) it then ripples to any other loaded viewmodel that also uses the same model.
DataContext
Going a bit further, you could create a datacontext module that manages the data in the models. You ask the datacontext for a model (ex: list of customers) and the datacontext checks if it has them cahced already and if not, it goes and gets them from an ajax call. Either way that is abstracted from the view model and models. The datacontext gets the data and returns a model(s) to the viewmodel. This way you are very decoupled, yet you can share the data (your models) via the datacontext.
I could go on and on ... but please tell me if this is answering your question. If not, happy to answer any other specifics.
** Disclaimer: I'm building a Pluralsight course on SPA's (using Knockout and this strategy) :-)
This is a popular field of interest right now, so I expect you will get some better answers, but here goes.
The Model
Yes, you should absolutely have a server-side representation of the data, which is your model. What this is depends on your server, and your database. For MVC3, this is your entity model. For Django or Ruby, your will have defined db models as part of your db setup. This part is up to your specific technology. But agian, yes you should have a model, and the server should absolutely perform data-validation.
The Application (ViewModel)
It is recommended that your views each have their own viewmodel. Your page could then also have a viewmodel, an App Viewmodel if you will, that keeps track of all of them. If you go this route, the app viewmodel should be responsible for switching between the views, and implementing any other application level logic (like hash bashed navigation, another popular single page tool). This hierarchy is very important, but not always simple. It will come down to the specific requirements of your application. You are not limited to one, flat viewmodel. This is not the only possible method.
Ad Hoc Example:
var ThingViewModel = function(name, data){
this.name = ko.observable(name);
//Additional viewmodel stuffs
};
var AppViewModel = function(initialData){
//Process initial data
this.thing = new ThingViewModel(someName, someData);
};
I am working on a similar project right now, purely for study (not a real world app), that is hosted here on GitHub, if you would like to take a look at some real exmaples. Note, the dev branch is quite a bit ahead of the master branch at the moment. I'm sure it contains some bad patterns (feel free to point them out, I am learning too), but you might be able to learn a few things from it anyway.
I have a similarly complex solution in which I am reworking a WPF application into a web version. The WPF version dealt with complex domain objects which it bound to views by way of presenter models.
In the web version I have implemented simplified and somewhat flattened server-side view models which are translated back and forth from / to domain objects using Automapper. Then those server-side view models are sent back and forth to the client as JSON and mapped into / onto corresponding Knockout view models (instantiable functions which each take responsibility for creating their children with sub-mapping options) using the mapping plugin.
When I need to save / validate my UI, I map all or part of my Knockout view model back to a plain Javascript object, post it as JSON, the MVC framework binds it back to server-side view models, these get Automapped back to domain objects, validated and possibly updated by our domain layer, and then a revised full or partial graph is returned and remapped.
At present I have only one main page where the Knockout action takes place but I anticipate that like you, I will end up with multiple contexts which need to deal with the same model (my domain objects) pulled as differing view models depending on what I'm doing with them.
I have structured the server side view model directories etc in anticipation of this, as well as the structure of my Knockout view models. So far this approach is working nicely. Hope this helps.
During a project i developed a framework (which uses KnockoutJS) which provides decoupled View/ViewModel pairs and allows to instantiate subviews in a view. The whole handling of the view and subview instantiation is provided by the framework. It works like MVVM with XAML in WPF.
Have a look at http://visto.codeplex.com
I am writing a module based javascript website, backed by a Mysql DB.
Each module talks with the DB through PHP.
On the UI, for simplicity, the module on the left will display all relevant rows, with edit(write) functionality. The module on the right display the data from the same DB, with write access too.
So each would affect the other in each update.
I'm told backbone would be a good framework. Then, I have read the todos example, and understand how there are item->itemList, view->viewList, etc...
But now, the question is, how do I apply it to this situation?
Which is an item, a view in this situation?
The module on the left and the module on the right are Views, each of which can be made up of other views.
Within the model don't store a reference to the view (as I've seen done in some of the examples):
this.view = view; //view being passed in as an arg
The reverse (a view storing a reference to a model) is okay. Your views should be doing most of the work, listening to and responding to model events. Thus, in the view initialize method you might:
model.bind("interesting-event", function(){
//the view updates/reacts to the model.
});
Also, never add a model to two collections (just one ever). When a model is assigned to a collection, Backbone sets a reference on the model that points to the owning collection.
Incidentally, the a-model-cannot-belong-to-two-collections issue is the reason why you don't want a model referencing its view. A model can have many views on one screen.
Backbone is perfect for your needs. Start with a very basic version of your app and keep fleshing it out. All the while keep reading about Backbone online. I read everything I could find (there's not a whole lot, not really). The key concept is simply event based programming (much like you'd use in VB or lots of other platforms). It's a lot of trial and error, but you'll make sense of it with practice.