问题
I'am searching for a way to filter my backbone collection with the value from a input field - to achieve this, I defined an event listener with the view ("keyup input.searchBookmark": "search"):
window.BookmarksListView = Backbone.View.extend({
events: {
"keyup input.searchBookmark": "search"
},
el: $('#bookmarksList'),
initialize: function() {
this.model.bind("reset", this.render, this);
this.model.bind("add", function(bookmark) {
$('#bookmarksList').append(new BookmarksListItemView({model: bookmark}).render().el)
});
},
render: function(eventName) {
_.each(this.model.models, function(Bookmarks) {
$(this.el).append(new BookmarksListItemView({model: Bookmarks}).render().el);
}, this);
return this;
},
renderList: function(bookmarks) {
alert(bookmarks);
},
search: function(event) {
alert(event);
var query = $("#searchBookmark").val();
this.renderList(this.model.search(query));
}
});
The HTML:
<form class="pull-left" action="">
<input placeholder="Bookmarks..." type="text" class="searchBookmark" id="searchBookmark" value="">
</form>
The input element is not within the element "bookmarksList".
My problem is that nothing happens if I enter some text into the input - what could be the problem?
回答1:
When you use an events object in a Backbone view, they are bound using jQuery's delegate:
delegateEvents
delegateEvents([events])Uses jQuery's
delegatefunction to provide declarative callbacks for DOM events within a view. If aneventshash is not passed directly, usesthis.eventsas the source.
So only elements that are within the view's this.el will be bound using the view's events. You say that
The input element is not within the element "bookmarksList"
so nothing gets bound to input.searchBookmark and your search method never gets called.
You have a few options:
- Move the search box into
#bookmarksListso that the list is self-contained. - Move the search event handling to the view that contains the search box. Then set up a separate collection of bookmarks for
#bookmarksListto display and update the display when the collection changes. Then the view with the search box can filter the main bookmark collection, update the collection that#bookmarksListuses, and let Backbone's event handling take it from there. - Manually bind to
input.searchBookmarkwhen your#bookmarksListview is rendered and unbind in itsremovemethod.
The first two are pretty standard Backbone setups so there's not much more to say about them; the third is a bit odd and would look something like this:
window.BookmarksListView = Backbone.View.extend({
events: { },
initialize: function() {
_.bindAll(this, 'search');
//...
},
render: function(eventName) {
$('input.searchBookmark').on('keyup', this.search);
//...
},
remove: function() {
$('input.searchBookmark').off('keyup', this.search);
// Other cleanup...
},
//...
});
I don't recommend this approach though, your views should keep their hands to themselves.
回答2:
I am handling filtering by having a View for the input field which triggers a message:
class App.Views.SidebarListSearchView extends Backbone.View
el: "input#list-search"
events:
keyup: "filter"
# Send a message with the value we are searching for.
filter: => App.Mediator.trigger("filterLists", $(@el).attr("value"))
... that other Views listen to:
class App.Views.SidebarFolderView extends Backbone.View
...
initialize: ->
# Re-render the shebang with a filter applied.
App.Mediator.bind("filterLists", @filterLists)
...
来源:https://stackoverflow.com/questions/9244773/backbone-js-filtering-a-collection-with-the-value-from-a-input