问题
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
delegate
function to provide declarative callbacks for DOM events within a view. If anevents
hash is not passed directly, usesthis.events
as 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
#bookmarksList
so 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
#bookmarksList
to 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#bookmarksList
uses, and let Backbone's event handling take it from there. - Manually bind to
input.searchBookmark
when your#bookmarksList
view is rendered and unbind in itsremove
method.
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