简体   繁体   中英

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

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?

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.

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)

        ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM