Here's the fiddle:
Code is down below. Making a chat app and need a sorted, connected user list. Figured Collection with a comparator on name hooked to a CompositeView should do it. Am I doing something wrong in the implementation here?
HTML:
<div>Enter user name and hit add user to build your list</div>
<div id="divadduser">
<input id="inputusername"/>
<input id="buttonadduser" type="button" value="add user"/>
</div>
<div id="divusers"></div>
JAVASCRIPT:
var nextAvailableUserId = 0;
//Define a region to show a list of users
var userListRegion = new Backbone.Marionette.Region({ el: '#divusers'});
var ConnectedUserModel = Backbone.Model.extend();
//Make a user item view
var UserView = Backbone.Marionette.ItemView.extend({
template: Handlebars.compile(
'<a id="{{id}}">{{name}}</a>'
),
tagName: "li",
});
//Define a user collection
var UserCollection = Backbone.Collection.extend({
model: ConnectedUserModel,
comparator: "name"
});
//Make a user collection instance
var collConUsers = new UserCollection();
//Define a composite user list view
var UserListView = Backbone.Marionette.CompositeView.extend({
template: Handlebars.compile(
'<ul id="ulusers"></ul>'
),
itemView: UserView,
itemViewContainer: 'ul',
collectionEvents: {
"add": "doSort"
},
doSort: function () {
this.collection.trigger('reset');
}
});
//Make a composite user list view instance
var view = new UserListView({
collection: collConUsers
});
//Show the view
userListRegion.show(view);
//Handle add user button click
$('#buttonadduser').click(function () {
var uName = $("#inputusername").val();
if (uName.length > 0) {
nextAvailableUserId += 1;
collConUsers.add([{ id: nextAvailableUserId, name: uName }]);
$("#inputusername").val('');
}
});
UPDATE:
I'm leaving this marked answered but the solution below is not optimal. In essence it overrides how CollectionView or CompositeView appendHtml. Technically this helps the issue described in this thread but it seems to create other problems. In my case I also have a JQuery filter on my user list (like this - http://kilianvalkhof.com/uploads/listfilter/). This override breaks that filter. Not sure why just yet. If I discover why I'll update this post.
After a few days on this I've found no reliable BB marionette way to sort on add AND filter on each keystroke a user list without rendering duplicate models. If I do I'll update. But I just think the benefit of the collection/view bond here is not fully realized without this piece. I did this with minimal difficulty in AS3.
I think the real answer is that views should accurately represent the state of a model. If a model has had an addition and been sorted, a view should reflect that. Duplicate model rendering feels like a bug.
UPDATE:
Learning as I go here. You have to specify in the override precisely where you want your content to go. As such, my 'ul' itemViewContainer is no longer relevant. So the final answer for me was:
- Ditch itemViewContainer
- Override appendHtml to tell my CompositeView explicitly where my users ul was and also to insert users by index according to sort order
- Ditch my "add" collectionEvent and handler
Whew...