0

Previous Title :- Search functionality in Backbone.js.

I am working on Backbone.js to achieve search functionality( when user types something in search textbox, the list should get filetered as per search criteria).

For this I have my controller as :-

var departments = backbone.Collection.extend({
    model: departmentModel,
    url: '/MyController/GetDepartments',
    comparator: function (department) {
        return department.get('name');
    },
    initialize: function () {
        this.selected = [];
    },
    search: function (letters) {
        if (letters == "") return this;

        var pattern = new RegExp(letters, "gi");
        return _(this.filter(function (data) { //without wrapping the filter with the underscore function, the filter does not return a collection
            return pattern.test(data.get("Name"));
        }));
    }
});

return departments;

In my Backbone View I have my keyup event defined on search textbox

 "keyup #searchDepartments": "searchDepartments",

Where my searchDepartments is -

searchDepartments: function (e) {
    var letters = $(e.currentTarget).val();
    var searchResult = this.collection.search(letters);
    var collection = new departmentCollection(searchResult.toArray());
    //  debugger;
    this.renderFileteredData(collection);
    //$(e.currentTarget).val(letters);
}

Lastly, renderFilteredData is simple

renderFileteredData: function (departments) {

     $(this.$el).html(this.template(departments.toJSON()));

     return this;
 },

Now the issue is- when ever I am typing any text the list gets filtered out but the search text goes off. Whats wrong?

EDIT:- As per suggestions, now I have created a different view as below for search text box:-

function ($, _, backbone) {
    'use strict';
    var searchDepartmentView = backbone.View.extend({
        el: "#search-container",
        tagName: 'div',
        template: Handlebars.templates.DepartmentSearchView,
        initialize: function () {
            //this.render();
            return this;
        },
        render: function () {
            console.log('in search departmnet view render method');
            // $(this.$el).html(this.template());// I am trying to render this template.. But its not working
            this.$el.html('in search departmnet view render method');//Passing dummy value to it
            return this;
        }
    });

    return searchDepartmentView;
});

and in my main view :-

render: function () {
    //  _.bindAll(this, "search");
    this.innerView = new departmentSearchView();

    $(this.$el).html(this.template(this.collection.toJSON()));

    this.$el.find("#search-container").html(this.innerView.render().$el); //Tried approach 1 as suggested
    // $(this.$el).html(this.innerView.render().el);//Tried approach 2 as suggested

    return this;
},

Now, I am not getting my search text in search departmnet view render method displayed in main view

Shubh
  • 6,693
  • 9
  • 48
  • 83
  • It's a little hard to say without seeing your markup, but are you sure you're not overwriting the element when you are rendering your html (`$(this.$el).html`..? Another thing `$el` is already a jQuery object so there is no reason to wrap it in a jQuery object (`$()`). – Jack Nov 27 '13 at 14:27
  • 1
    it sounds like the view that contains your search box is rerendered. – Yurui Zhang Nov 27 '13 at 14:33
  • @Jack- I am not very sure.. but if I am overwriting the element then how do I handle it? – Shubh Nov 27 '13 at 14:34
  • @YuruiRayZhang You may be right. I am quiet new to backbone. How do I handle it? – Shubh Nov 27 '13 at 14:38
  • @ShubhDasgupta you can have a designated element for your *search results* and then instead of `this.$el.html(...` you can do `this.$el.find('#searchResultsContainer').html(...` – Jack Nov 27 '13 at 14:40
  • You can either put your search results in another view/container, or move your search box into a different view. – Yurui Zhang Nov 27 '13 at 14:44

1 Answers1

0

Finally, I found a way to do it. Thank to the great answer by Kelvin Peel in how-to-handle-initializing-and-rendering-subviews-in-backbone-js

Thanks to YuruiRayZhang for his suggestions!

Code snippet from there, which describes a detailed process of nested views :-

var ParentView = Backbone.View.extend({
    el: "#parent",
    initialize: function() {
        // Step 1, (init) I want to know anytime the name changes
        this.model.bind("change:first_name", this.subRender, this);
        this.model.bind("change:last_name", this.subRender, this);

        // Step 2, render my own view
        this.render();

        // Step 3/4, create the children and assign elements
        this.infoView = new InfoView({el: "#info", model: this.model});
        this.phoneListView = new PhoneListView({el: "#phone_numbers", model: this.model});
    },
    render: function() {
        // Render my template
        this.$el.html(this.template());

        // Render the name
        this.subRender();
    },
    subRender: function() {
        // Set our name block and only our name block
        $("#name").html("Person: " + this.model.first_name + " " + this.model.last_name);
    }
});

Also, an extended tutorial for the above mentioned process backbone-js-subview-rendering-trick/

Community
  • 1
  • 1
Shubh
  • 6,693
  • 9
  • 48
  • 83