Maintain A Stack Of Marionette Itemviews Within A Marionette Layout
Solution 1:
Use a backbone router to listen to URL change events. Setup routes for each of your views and then have the router call the layout to change the view it's displaying in response to each route. The user could click back or forward any number of times and the app responds accordingly and displays the correct view. Your router might look like:
varRouter = Backbone.router.extend({
routes: {
'my/route/itemViewA': 'showItemViewA',
'my/route/itemViewB': 'showItemViewB'
},
showItemViewA: function () {
layout.showItemView('a');
},
showItemViewB: function () {
layout.showItemView('b');
}
});
Your layout might look something like this:
varLayout = Backbone.Marionette.Layout.extend({
regions: {
someRegion: 'my-region-jquery-selector'
},
initialize: function () {
this.createViews();
},
createViews: function () {
this.views = {
a: newBackbone.Marionette.ItemView,
b: newBackbone.Marionette.ItemView
};
},
showItemView: function (view) {
this.someRegion.show(this.views[view]);
// You might want to do some other stuff here// such as call delegateEvents to keep listening// to models or collections etc. The current view// will be closed but it won't be garbage collected// as it's attached to this layout.
}
});
The method of communication between the router and the layout doesn't have to be a direct call. You could trigger further application-wide events or do anything else you can think of. The router above is very basic but gets the job done. You could create a more intelligent router to use a single route with parameters to determine dynamically which itemView to show.
Every time the user does something that requires changing views, you can update the browser's history by using router.navigate('my/route/itemViewB', {trigger: true});
. Also, if you set up your app to only render on history change events then you don't need to set up two mechanisms for rending each view.
I use this pattern in my own apps and it works very well.
Solution 2:
@Simon's answer is headed in the correct direction. However, the only way to stop Marionette from closing views is to modify a bit of it's Region code.
var NoCloseRegion = Marionette.Region.extend({
open: function(view) {
// Preserve the currentView's events/elementsif (this.currentView) { this.currentView.$el.detach(); }
// Append the new view's elthis.$el.append(view.el);
}
});
The, when be sure to specify our new Region class when creating the Layout view
varLayout = Backbone.Marionette.Layout.extend({
regions: {
someRegion: {
selector: 'my-region-jquery-selector',
regionType: NoCloseRegion
},
},
initialize: function () {
this.createViews();
},
createViews: function () {
this.views = {
a: newBackbone.Marionette.ItemView,
b: newBackbone.Marionette.ItemView
};
},
showItemView: function (name) {
// Don't `show`, because that'll call `close` on the viewvar view = this.views[name];
this.someRegion.open(view)
this.someRegion.attachView(view)
}
});
Now, instead of calling show
which closes the old view, renders the new, and attaches it to the region (and triggers a few events), we can detach the old view, attach the new, and open it.
Post a Comment for "Maintain A Stack Of Marionette Itemviews Within A Marionette Layout"