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
Related
I have an array of items populated by an AJAX call in a knockout ViewModel, which displays a few fields of data for each item on a web page.
Now I need to enable the user to click on one item populating a side bar with data which was received from the previous AJAX request (a few fields plus a lot more).
I suppose typically one would take an id and do an item specific AJAX request, routing it through Sammy.js, but we don't need to.
I'm new to knockout; best policy I imagine is to have a ViewModel for the various divs to display the data, but how to get the ViewModels to pass data between themselves? Is this taboo?
Making reference to the other window via the window object?
Using the with: keyword? It keeps cropping up, but I can't see how to apply that in this context.
Perhaps going via Sammy.js, and caching the data in Amplify?
This is an example of drill-down functionality, and I've read a number of StackOverflow Q&A about this but couldn't find up something I can use. I've got up to this stage by following John Papa's PluralSight tutorial.
You may want to go with a pub/sub model either with Amplify's messaging or the library the #RPNiemeyer mentions above. Both are excellent.
However it sounds like you just want to grab the data from the server, then use that data in multiple view models. Perhaps even sharing some of that data in multiple view models. The datacontext concept in my SPA tutorial allows you to host data in the datacontext and reference it from other view models.
You could also use a library like Breeze to help do this (Breeze would replace the datacontext in my SPA ... and be better at it as I will show in an upcoming course).
These are just a few options
You may also want to checkout the "Share an EntityManager" post under "Cool Breezes" in the breeze documentation.
The sharing a single EntityManager is probably all you need. But if you think you need more than one, read "Multiple managers".
IMO The easiest way to do it is to simply pass "params" with an observable containing data to your sidebar component.
http://knockoutjs.com/documentation/component-custom-elements.html#passing-observable-expressions
As was mentioned in comments, the good choice would be to use knockout-postbox
knockout-postbox is a Knockout.js plugin designed to use Knockout's basic pub/sub capabilities to facilitate decoupled communication between separate view models / components.
This allows you to set up simple topic-based communication like:
var ViewModelOne = function() {
this.isEditable = ko.observable();
};
var ViewModelTwo = function() {
this.editable = ko.observable(false);
};
var one = new ViewModelOne();
var two = new ViewModelTwo();
var editableTopic = "myEditableTopic";
one.isEditable.subscribeTo(editableTopic);
two.editable.publishOn(editableTopic)
I have read and even run a sample application that is fully implemented on backboneJS and Django. But am kinda lost how backboneJS is handling this stuff. I need a simple dummy explanation on how backboneJS is receiving the JSON data, building the model, building the collections and listing the data in its view.
Data is displayed in html div tag called "#person"
This is the RESTful/JSON data coming from my server
{"objects":[{"id":"1","name":"John","age":"20", "gender":"male"},{"id":"2","name":"Mary","age":"30","gender":"Female"}]}
Things am looking for in the explanation are;
What is the first function/object created/called by BackboneJS ( entry point )
How does backboneJS tell the views to display the data received?
How does backboneJS model map to the individual fields in the JSON data (id, name, age)
How can i peep in the collections/models created by backboneJS using browser javascript console?
If i have a data entry form with the same fields as the JSON data, using backboneJS, how will i be able to POST the data back to the server, which objects/functions will backboneJS use to perform this task?
Any extra information will be highly appreciated.
Gath
1. What is the first function/object created/called by BackboneJS ( entry point )?
Backbone.js follows MVC architecture. Model defines the actual structural design of model. View defines how the application visually displayed. This view will create the instance of Model and it will be used in the application.
So, in backbone application, Instance of view is created first. When we create an instance of View by calling new myView();, initialize() function will be called first. Model can be instantiated from View as per the requirements.
2. What is the first function/object created/called by BackboneJS ( entry point )?
When you create the instance of model, you can provide the data through that instance. There are getters and setters available for Model.
For example, User is the Model for above JSON. Model is instantiated as below.
var user=new User({“id”:”1”,””name”:”john”,”age”:20,”gender”:”male”});
You need to access the JSON object to define the model.
3.How does backboneJS model map to the individual fields in the JSON data (id, name, age)?
As said before, individual fields can be mapped while instantiating or with the getter and setters of backbone.js
4.How can i peep in the collections/models created by backboneJS using browser javascript console?
You can console the java script objects with toJSON() function. Usually, underscore.js provides more utility functions in backbone.js.
You need to browse through backbone.js documentations.
Addy Osmani did a fine job of explaining that and going even bit more into details down here -> https://github.com/addyosmani/backbone-fundamentals
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.
I am looking through alot of the Knockout JS documentation available, however it doesn't seem to follow the MVVM pattern as I would expect (when looking at Wikipedia's definition of MVVM).
In all the examples they seem to show source code for ViewModels and Views however there is never a model, now it seems like most of the functionality that the model should contain (saving/retrieving a representation of data) is put within the ViewModel. I thought that maybe the ViewModels were actually more akin to the Model, and the binding layer that you kinda get for free is the ViewModel, as that does all the bindings...
So I am just wondering if I am missing something here? As I have a question open at the moment about where my UI logic should go, i.e adding Watermarks, Inter-View chatter etc and I haven't really got a solid answer for it, so wanted to confirm that my understanding of the pattern usage within this framework is correct before continuing.
In Web development, the Views and ViewModel are at the client-side.
The Models are at the server side.
The models represent the real objects while the View Models only represent them in terms of the view in which they are displayed e.g. in Customer Model you have all the information related to the Customer but in a Customer View Model you might only have Customer Name (because that's all your showing on the view).
Most of the knockoutjs example don't explain the Model bit is because it is server-side dependent and could be written in Ruby/C#/Python etc. Knockout only deals with the View Model and View; It's server side agnostic.
The server side tech is required to develop the Model layer in MVVM. Knockoutjs is required to develop the VM-V layer.
I'm building an extremely JS-heavy web application. I say it's JS-heavy, because the vast majority of the work going on is done on the client (although there is some syncing back and forth to the server using AJAX and XMPP).
This is my first time building something of this scale in pure JS (using jQuery), so I began by organizing my code using MVC in a manner modeled after Rails. For example, if the user clicks a button, a method is called in the Controller object, which pulls some data from the models, and which then passed the data a view function. I do this for pretty much everything, even trivial actions like showing a small popup.
After a few months of this, I feel like I'm not taking full advantage of the language. Should I really be rendering my views as if they are webpages?
It seems like it'd make more sense to break down the views into components, which would be instances of Javascript objects/functions. For example, instead of...
var itemListHTML = '<ul id="item-list"><li>item1</li><li>item2</li></ul>';
jQuery('#container').html(itemListHTML);
...I could instead have...
components.itemList.render();
So here, there's just a component called itemList. Since all the data is stored on the client, these components could instantly access all of the data necessary to create and manage themselves. I imagine I would still use MVC, but there'd be no need for controller actions that are responsible for the entire view. If I want to refresh one part of the UI, I just call whateverComponentControlsThatArea.redraw() and it re-renders itself.
I'm sure someone had done this before. Is there a name for this style of code organization? Any guides or best-practices for how to implement it?
There are a number of javascript MVC frameworks available now
JavaScriptMVC, PureMVC, Sammy.js for example.
Rendering of views or sub-views in normally handled through some kind of templating engine.
JavaScriptMVC has a module EJS, which is modelled on ERB, which I have found quite useful. Templates can be compiled into functions to speed things up for production.
There are other templating solutions too for example John Resig's Micro-Templating and many more
I recommend you use one of these frameworks if it's not too late. I've used JavaScriptMVC for a few projects now and can recommend it (The docs take some getting used to though)
You should really look into jquery.tmpl (http://api.jquery.com/jquery.tmpl/) for creating fast javascript templating ideal for building your view rendering.
A little late to the party, but I've got $0.02 here that I'm not sure what to do with...
Forgetting about (typical) Web-MVC (ie: RailsMVC, et cetera) for a second:
Consider that JavaScript can all be resident in the same place, and that you don't have to worry about figuring out routing and class-instantiating (unless you really want to).
Ideally, from a software point of view, what you want MVC to do is to separate what the user does, from what makes up the content (based on the action), from what makes up the view (based on the action).
There's nothing saying that you can't have multiple views, or even that you can't have a view which contains multiple views (which might use templates, or be functionally generated, and attached to a DOM-node - either is valid).
In a simple pseudo-example, rather than having a flow that looks like:
Action Loads Controller -> Controller Loads Model -> Controller Queries Model -> Model Answers Controller -> Controller Loads View -> Controller Feeds Data to View -> View Sends Page to Controller -> Controller Outputs Page
Why not something like:
Controller Listens for Action (addEventListener) -> Controller Turns Action into State-Logic -> Controller Notifies Model (observer) OR Model Polls Controller -> Model Changes State based on Logic, and Collects / Sorts all Data -> Model Notifies View (observer) OR View Polls Model -> View Changes State based on Logic -> View Renders all Components, based on Data + ViewState (innerHTML OR documentFragment).
It looks a little longer, but in reality, everything is nice and separate.
With the View (or View Manager or however you want to think of it) dictating what windows are on the page, and how each window is made up, and where the data goes, inside of each article, in each window...
...now you have an MVC pattern, but you ALSO have the ability to say:
View["mainpage"] = {
data : { tweets : [{id:...}...]/* et cetera - pushed by Model, not Controller */ },
layout : [ "Header", "Carousel", "Articles", "TwitterFeed", "RSSFeed", "Footer" ],
// if your system is this clean, you could even prototype the content-builders
// rather than defining them in each ViewState - you'd just need layout, then
buildPage : function () {
var page = document.createDocumentFragment();
for (/* everything in this.layout */) {
View.build[this.layout[i]](this.data, page);
}
document.body.appendChild(page);
},
cleanUp : function () { /* fancy or simple DOM cleaning for state-change */ },
// grabs SubView by expected handle (id="tweetfeed" or whatever) and replaces it
// observer functionality, for views to automatically update as data changes
updateView : function (view, newData) { ... },
addData : function (data) { this.data = data; }, // for Observer
/* Observer - if you want to run the WHOLE site with AJAX from index.html
* clean up old (ex:"main") page and build and/or transition new (ex:"media") page
* could be unique for each page, for custom transitions, or just prototype it */
changeState : function (newState, newData) {
View["mainpage"].cleanUp();
View[newState].addData( newData );
View[newState].buildPage();
}
}
And now you've defined your whole main-page.
Of course, it's going to be extra work maintaining not only definitions for your main page, but for every page/section.
...and then, you need to make the functions which will create each sub-view -- but component-based design is EXACTLY what you were asking about.
In essence, for each widget, it will have its own building-logic.
That's what views do - they either have an individual template that gets reused, or they have a function that works the same way every time.
And an atomic view is one where you're dealing with a function that builds 1 item (1 Tweet, 1 Post, 1 Store item) and builds the view for that.
Having a Single_Tweet view post a single-tweet to the page, 20 times in a row would be a bad idea for JS performance.
But having a Single_Tweet view push tweets, in order, into a Tweets array that your Twitter_Feed view puts on the site is A-OK.
Even better is when your Pages are Views, made up of Widgets of Views, made up of Atomic-Units of Views.
And when all of that happens off-DOM (so innerHTML or documentFragment).
And the best would be a Framework where you define pages in this way, but you can also update an individual Widget, based on data-pushes from the Model, whenever you want.
And that's the beauty of AJAX -- old-fashioned MVC can happen, without a Controller that knows everything.
The Controller just holds a list of pressed-keys, the mouse coordinates, a clicked button's intent...
And it tells the Model that something happened.
The Model does everything state/data/data-manipulation (sorting) related, and feeds the new state or data to the view, which takes it all and puts it into HTML, in the order you specify.
That's about it.