I'm working on a Backbone app that contains a list of entries, much like the example app Todos (http://documentcloud.github.com/backbone/examples/todos/index.html).
So, I have an App view and one view per list item. Now, say I have a global edit button. The App view would handle a click and what I then want to do is tell each list view to show a delete button.
In the screenshots below (from Spotify), pressing the Edit button causes all list views to change appearance.
What's the best way to do this with Backbone. I need to iterate over all list views and call a editMode function. But the App view (out of the box) doesn't know about the list views..
I wrote up an article a while back on a few different options for coordinating between views: http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/
in your case, i'd recommend using the event aggregator that i describe in that article. you could have each item view listen for a "editmode" event, or something similar. when this event fires, each view that listened for it would update itself to go into edit mode. then you would do the opposite when you click "done" - send a "viewmode" event, or something similar, and have each view update itself appropriately.
My two cents: There is a simple "hack" you can do with backbone.js to actually have a pub/sub that can communicate between views:
Something along these lines (untested):
var EventBus = Backbone.Model.extend({
publish: function(event, args){
this.trigger(event, args);
},
subscribe: function(event, args) {
this.bind(event, args);
}
});
You basically get the idea. Now for every view, have it 'bind' to this EventBus (since views can only bind to models/collections in backbone) - you basically just use the method names publish/subscribe to be in sync with the nomenclature of such a model but you may choose not to. Just create an empty EventBus 'class' in that case and have every view bind to it :)
So every view only needs to be coupled to this EventBus and act on received events! Backbone.js internally handles all the plumbing of this design pattern, so you pretty much get it for free :)
The above code may not run as-is, but is there to give you an idea about it...
Related
(I'm using Prism Dryloc) My application consists of two views. The first contains a single list view displaying strings and the second - an entry and a button.
The listview is bound to an observable collection in the first page's View Model. How can I add to the observable collection from a different view?
Great question! You're essentially trying to pass data between views, and there's several ways of passing data between Views in Xamarin.Forms.
The two ways that seem relevant for your case:
Either making the ObservableCollection a public static object (so there's only one global instance of it). Not recommended.
The better way is to use the messaging center so that the second page publishes an event when the button is pressed, that the first page is subscribed to. And it passes that information that gets added to the list.
If these don't work, elaborate your use case and I'll suggest some more
If a have a collection with 50 models, it seems that I have 2 main options to render a list displaying 50 models:
- Option1 : Create a specific "item view" for each model and append these views to a main "list view". This will provide a direct relationship between each "item view" and each model, will be practical and inline with Backbone philosophy
- Option2 : Have only one "list view" rendering the list with "data-attributes" helping to fetch the corresponding model when an event happens on a given list item.
I understand that option 1 leverages Backbone in a much better way however I am concerned with the number of event listeners with this option. If I have 4 events that I have to listen to per item, this will mean that I will have 4x50=200 events listeners on my list... vs. 4 (delegated) events listeners with option 2.
Given that I want to use Backbone for a cordova application, which option would be the most appropriate ?
Maybe in that case it would be practical to used a "mixed" approach. A View for every model, but event listeners only on the top list view which will then delegate them further. This reduces event listeners on DOM elements.
Despite that - I would only use per-item-views when you need that extra functionality such as rendering and handling an edit form, or when single items are likely to be changed so that they need to re-render often. If that isn't the case use a single list view and let it handle the events.
hi i've been using backbonejs for almost 2 years now and am just starting out on marionettejs with my first app at this website.
the reason for my question is that in my app i have a Layout with a 2 composite view rendered as dropdown list and table (which updates itself whenever we change the selection on the dropdown list).
what i did was for the "change" event on my dropdown list, i have an MyApp.vent.trigger() which i have a listener at the MyApp.addInitializer() function that updates the other compositeview (the table below the dropdown list). actually for the whole app i have almost 6 of this triggers inside itemViews and compositeViews and listeners are inside the addInitializer() for some of the other functions.
i just want to know if i did this right? or is this how dev in marionettejs normally is?
thank you
Yes, that's the recommended idea. However, you don't necessarily need to use the top-level vent attribute: each sub-app and view has their own (scoped) event manager. In addition, you don't necessarily need to add the listener in an addInitializer.
Here's an example (from my Marionette book):
trigger an event at the view scope: https://github.com/davidsulc/marionette-gentle-introduction/blob/master/assets/js/apps/contacts/list/list_view.js#L15 This uses the triggers hash, but you could also do this.trigger("my:event") from within the view, like here: https://github.com/davidsulc/marionette-gentle-introduction/blob/master/assets/js/apps/contacts/list/list_view.js#L29
listening to the events (and retriggering them if necessary): https://github.com/davidsulc/marionette-gentle-introduction/blob/master/assets/js/apps/contacts/list/list_controller.js#L48 and https://github.com/davidsulc/marionette-gentle-introduction/blob/master/assets/js/apps/contacts/list/list_controller.js#L38
Hope this helps !
In cases where new items need to be added to a list via ajax, what is the biggest benefit of using something like Knockout.
So far what I have been doing is, on my view, use an editortemplate (with asscociated viewmodels) to render a list of items. Then to add a new item, I make a request to an action that loads a server-side viewmodel, and returns an EditorTemplte object which just gets appended to the list. Like this:
return Json(new { this.RenderPartialViewToString("MyEditorTemplate", model) });
The knockout way of doing things requires the implementation of another view model to display items, and then another template to display it. But doing it this way requires duplication of code since the view model has to be represented in 2 places: in the cserver side code and then the view for the knockout viewmodel. Isn't that bad practice?
Am I missing something, or understanding the purpose of knockout and MVVM?
The biggest benefit that you will see from Knockout is that you will not need to hit the server in order to add a new item to your list - everything happens client side. This has multiple benefits including:
You reduce load on your server.
You improve the end-user's experience.
You can keep multiple elements on the page up-to-date with your model without any server interactions.
Two great examples of this can be found at these Knockout tutorials:
Working with Lists and Collections
Loading and Saving Data
As far as duplicating code, if you take a look at those two tutorials, you'll notice that you don't need to duplicate code. For example:
Create a view to display your entire list.
To add a new item to the list, create a partial view that you load when you add a new item to the page - that partial view is bound to Knockout
When you submit the entire form, everything in that list will be submitted - including those items you added via Knockout.
Your ViewModel will be specific to your list item (you don't need to create an entire ViewModel for everything, necessarily). And your view is specific to a single list item.
Hope that's clear. Knockout is pretty straightforward and they have some great documentation and tutorials to help you move forward.
IMHO, the following is cleanest option for the architecture of knockout and asp mvc mixed together.
Have your ASP.net acting as a webservice and have knockout control all your view templating and logic.
Otherwise, yes there will be potential replication of viewmodels and having to refactor both front and backend code when you need to change your model.
First of all, I'm using MVVM for this and I would like to continue using it and ofc using the best practices as well.
I have a Mainpage which will display a list of items. On another page you can add such items. The items will be saved in a database which came with the Mango update.
When a item is added I want to navigate back to the mainpage and I want the list to be updated automatically. Is this possible and what's the best way? I'm thinking of following scenario's:
Use the Refresh query string when you navigate. Check in the back end of your main if there is a refresh. Then send a message 2 the ViewModel that he needs to update his list. I have tried this and this works. But this doesn't really sound the right way for MVVM.
Can't this be done with the NotifyPropertyChanged event that you can raise on your Database Model ? Or doesn't it work over different pages?
Reload the whole ViewModel for the main page somehow.
Any other idea's?
Use MVVM-Lights Messenger. The MainViewMode can subscribe to a Refresh event and the ViewModel where the items are added can publish a Refresh event.
This is a good example of how messenger can be used.