backbone.js - filtering a collection with the value from a input

痞子三分冷 提交于 2020-01-24 19:41:06

问题


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 an events hash is not passed directly, uses this.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:

  1. Move the search box into #bookmarksList so that the list is self-contained.
  2. 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.
  3. Manually bind to input.searchBookmark when your #bookmarksList view is rendered and unbind in its remove 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!