In an MVC controller is what holds the business logic. In backbone the
controllers have been renamed to route. Now there are couple of things
which bring in confusion.
Model should have business logic.
Collection is the collection of models.
Views are where the templates are rendered, and most of the DOM
event handling is done.
Apart from routing, what do the routers do? And where should more
of business logic go to the routers or to the models?
Do the views perform anything extra other than rendering DOM
variables?
Yes they should, also should be the ones with a "link" to the Backend, to do the CRUD, but can also validate object state, ensure backend and frontend model sync and other things.
Correct again, but they also have a very nice use that is to fetch lists of models from the server very easily.
They should also attach event handlers to HTML elements and models and react to those events accordingly.
4.They handle all URL changing events and direct them to display the proper views for that URL, routers give you the opportunity to change your page completely and keep track of the URL changes by using Backbone.history, so Back and Forward Browser buttons will keep working.
They do the URL mapping.
It's an awesome framework, I can't live without it anymore.
IMHO:
You don't need to use routers et all, if you use them the should just route.
Views should contain all the DOM/Model-Event listeners.
Some Ideas on structuring: http://ricostacruz.com/backbone-patterns/
Related
My routes look roughly like this:
```
/
/sites
/:site_id
/settings
/user-defined-params
/:param_id
```
Now in /user-defined-params I want to display table-list of parameters assigned to that given site. The models are not related, I mean site doesn't have collection of params as a relation, so I can't simply fetch them via this relation.
Should model() hook for my router return list of these params? By default the model seems to be site loaded from parent route (:site_id). What if loading takes some time and I'd like to actually display this table (so do actual transition) but then show kind of loading indicator waiting for table to fill in with the data.
When I try to load this in model() hook, transition blocks. When I try to load it in afterModel() hook, I don't have a way to assign it and make it available for template (other than force-assigning params property to site model, which seems to be wrong).
All the examples I've found over the Internet seem to be lacking this scenario, which I feel is one of the basic ones, so any hints on that? How should I load it (ideally without blocking transition)?
The defaults in Ember's current router (as you have found) are to block UI loading completely until the promised returned in model hooks have resolved. However, there's interest in adjusting that so we can easily build non-blocking UI patterns with the built-in router.
Right now, the community consensus here is to use ember-concurrency and it's derived state (specifically the .isRunning aspect of tasks) to toggle between a loading state and a screen with the data rendered. It isn't a coincidence that ember-concurrency was built by the guy behind the first router and the current router re-think that is in-process.
One example of an approach to this is outlined here:
https://emberway.io/skeleton-screen-loading-in-ember-js-2f7ac2384d63
I personally prefer to use my route to do the initial task loading and the consume the data in the template. But in a more complex UI I also will go with container components as outlined in that article.
I am quite experienced with JS and Backbone, but want your help brainstorming a best practise solution to the following problem:
There are two views. They sit side-by-side running concurrently in the page.
Both of these views are passed the same instance of a model.
Both of these views have actions which can update the model.
How, using Backbone's event driven programming, do you think would be the best way of distinguishing the events fired from view to view.
A possible scenario could be:
The user performs an action which updates the model in an invalid way on View A. But as the user did not perform it on View B they should not be notified there.
You can use intermediary objects to manage the flow between a repository (the object where the connection to the database takes place) and the instantiation / manipulation of views.
Instead of binding a model to a view from within the view, you can let the intermediary object (general purpose controller) make verifications, if required manipulations, before re-rendering the view with the modified model or collection.
Through the use of an event aggregator, you can trigger events from views from within the view, and listen to the event from within the "controller" object, who will in turn perform the required custom actions.
Using custom events seems simple enough. Just treat each view's actions as if they were different and name the events differently for each view (example this.trigger('view1:event1'), this.trigger('view2:event2')).
Make sure the views are subscribed to these specific custom events to avoid collisions on actions that would trigger events on both views (like attribute updates).
I have an app I am designing using node/mongo/angular, what I am not getting is how is the best way to get my data from mongo into my pages? I can use node, and thru my routes send back data from mongo with my template(hogan in this case), and bind using mustachejs. That works fine for most things. I have one screen that has a decent amount of drop down lists, to bind them for an edit scenario now seems a challenge. I would like to get them bound to an angular model and go about it that way. Is it better to get the data thru the route in node, then use something like ng-init and get it into angular? Or would I be better off not getting the data thru the route in node, and then using angular to perform a "get" request and bind that way?
From the documentation of ng-init, more precisely from the red warning alert at the top of the page...:
The only appropriate use of ngInit is for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
So no, do not use ng-init. While that can be a good strategy for lazy migrations from regular applications to single page applications, it's a bad idea from an architectural point of view.
Most importantly, you lose two things:
An API. The benefit of SPAs is that you have an API and that you're constantly developing and maintaining it, even before it has external users
A clean separation of concerns. Views are strictly limited to presentation, can be cached by the client and all data is transferred through JSON API endpoints.
I would say that the best way to get data from Mongo into your page, is as mnemosyn said, using an API.
Basicly, you can have your API route, f.ex '/api/data' configured and then it can be used by a angular service, (which can use ngResource to make things easier). Any controller that wishes to access this data can use the angular service to get it, do some stuff with it, and then update it using the same angular service.
I'm pretty new to this world so I need some clarifications on it. Maybe I could be wrong on the subject. So, feel free to correct me.
I'm studying how Marionette and Backbone work together. Oh yeah. Marionette gives us extension to Backbone. Really nice stuff.
The thing that is not obvious to me is when to use the routing mechanism provided by Backbone and when to use publisher/subscriber pattern by Marionette.
Is there any rule of thumb?
Here, Where to use event aggregator in backbone marionette?, a similar discussion but there is no advice on how using that or the other.
My take on the route management is explained in the free preview to my book on Marionette (http://samples.leanpub.com/marionette-gentle-introduction-sample.pdf)
Basically, my opinion (others don't necessarily share it) is that Backbone's routing should be used to configure the application state when the user "enters" the application via a URL. In other words, it will parse parameters, and call proper controller actions.
But once that initial state is setup, routing code should no longer be triggered, even as the user navigates through the application.
Here's an example:
The user enters arrives on the "contacts/2/edit". Backbone routing code will extract the 2 argument and call the edit controller action with that id parameter (which fetches that contact, displays the proper views, etc.). In other words, the initial application state is being configured.
The user clicks on the "show all contacts" link leading to the "contacts" URL. Here, I believe this modification should be handled through Marionette events (i.e. indicating the user wants to see all contacts). After all, we know what the user wants to do, and which URL fragment should be displayed. In other words, there is no reason for the routing code to get involved.
Note that this is my opinion, and other developers simply pass trigger: true when the user clicks a link. But as I explain in the book extract linked above, this tends to lead developers to create "stateless applications in javascript" (e.g. passing lots of parameters in the URL, even though they should be stored in the application's state). Ater all there is a reason that by default, Backbone's navigate method has trigger: false.
Derick Bailey (Marionette's creator) also discussed the issue here: http://lostechies.com/derickbailey/2011/08/03/stop-using-backbone-as-if-it-were-a-stateless-web-server/
Event aggregator is more useful for notifying things. (think small bits of feedback)
Message from server (updated record)
Let other models know things have changed
Lock everything down while saving until saved
Single Moment in time things
Router is for things where you want the state to be save-able (think separate page in a MPA)
Model Edit Page
Model View Page
Something that will stay until another event or activity changes it
If you are not sure if something is an event or a page, then think about it and ask that separate question.
backbone.js relies on restful applications to initialize models, but what about progressive enhancement? The data is already in the dom (or some of it), so should my models still make calls the the restful interface even though the html elements exist? Is there another library design that might be better suited for this case?
Backbone can handle that pretty well. The way I handle this case is to have a factory model that can receive a DOM node and parse it in order to extract data (id, fields and so on).
If you supply a 'el' option to a View constructor, backbone won't fetch nor render the model, so you can keep your node as is.
Upon data change, the controller will then sync to the server. You must be careful though to include whatever data your application needs to function whether it's displayed or not.
You should not use DOM element to initialize your model with backend data. You have a really nice infrastructure with backbone to not do this. When you rely on the DOM you need to change your javascript whenever the DOM structure change due to design for exemple.
Also do not rely on backbone view to create the model. It must go the other way around, the model dictate the views on the page.
Just add a script element and create your JS objects directly in there. You can initialize collections, single models, etc.
You can do the same with templates or DOM UI building blocks:
<script type="text/js-template">
<!-- Your template as realy do elements or using a js templating engine like _.template-->
</script>
Load up your page and have your app play locally.