1
votes

I'm a junior javascript developer, got an internship in a company that uses Backbone and Marionette. My first task is to create searching, filtering and sorting functionality in a collection based in some inputs, the thing is i got 2 differents views: one itemView renders the input fields(search field, sorting selection,etc ) and a collectionView renders the collection.

I've bee analizing backbone event aggregator, listenTo method, etc to find a way to make the collectionView listen to submit, click events in the itemView so it can render itself accordingly. For example when the user enters "frog" in the search field, the collectionView displays models containing that criteria, if the user clicks the last modified sorting option, the collectionView renders itself that way.

Any suggestion is really welcome. Thanks in advance.

1

1 Answers

0
votes

Basically Marionette does everything for you, you just need to initialize collection view properly.

You can specify which child view events your collection view should listen to (anyway it listens to some default events by default)

Here is example of search functionality and event handling of child views:

HTML

<script id='itemViewTemplate' type = "text/template">
     <div class='itemView'><%= title %></div>   
</script>
<script id='collectionViewTemplate' type = "text/template">
    <div class="collectionView"></div>
</script>

<input value='' id='search' placeholder='search'>

Javascript

// our data to show and filter
var data = [
    {title: "title 1"},
    {title: "title 2"},
    {title: "title 3"}
];

// item model
var FooBar = Backbone.Model.extend({
  defaults: {
    title: "" 
  }
});

// collection of items
var FooBarCollection = Backbone.Collection.extend({
    model: FooBar
});

// item view
var FooView = Marionette.ItemView.extend({
    template: "#itemViewTemplate",

    events: {
        "click": "_onClick"
    },

    _onClick: function() {
        this.trigger('click', this); // here we trigger event which will be listened to in collection view
    }

});

// collection view
var MyCollectionView = Marionette.CollectionView.extend({
    childView: FooView,
    template: "#collectionViewTemplate",

    childEvents: {
        'click': '_onItemClick' // listen to any child events (in this case click, but you can specify any other)
    },

    _onItemClick: function(item) {
        $('.message').text("item clicked: " + item.model.get("title"));
        console.log(arguments); // event handler
    }
});

// init our collection
var myCollection = new FooBarCollection(data);
// another collection which will be filtered
var filterCollection = new FooBarCollection(data);

// init collection view
var myCollectionView = new MyCollectionView({
    collection: myCollection
});

// render collection view
$("body").append(myCollectionView.render().$el);

// search
$('#search').change(function() {
    var value = $(this).val(); // get search string 
    var models = filterCollection.where({
        title: value
    }); // find models by search string

    value ? myCollection.reset(models) :   myCollection.reset(filterCollection.models); 
// reset collection with models that fits search string.
// since marionette collection view listens to all changes of collection
// it will re-render itself
//  filter collection holds all of our models, and myCollection holds subset of models, you can think of more efficient way of filtering
});
// just to show click event info
$('body').append("<div class='messageContainer'>Click on item to see its title:<div class='message'></div></div>");

Marionette collection view listens to all myCollection events, for exaple

If you'll write

myCollection.add({title: 'title 4'});

It will automatically render new itemView in collection view. Same for remove, reset and other defaut Backbone.Collection methods (which trigger events, and marionette listens to them);

Here is jsfiddle: http://jsfiddle.net/hg48uk7s/11/

And here is docs on marionette:

http://marionettejs.com/docs/v2.4.3/marionette.collectionview.html#collectionviews-childevents

I suggest to start reading docs on marionnet from beginnig, because CollectionView inherits a lot from ItemView and ItemView inherits a lot from View and so on, so you could know all the features Collection.View has.

UPDATE

Maybe I misunderstood a question a bit, you need a communication between collectionView and some other view (itemView in this case another view, not the view collectionView uses to render its children, that's what I thought). In this case, here is an updated fiddle:

http://jsfiddle.net/hg48uk7s/17/

You need third entity to handle communication between collectionView and searchView for example. Usually it some controller, which listens to searchView events, then calls some handler, giving control to collectionView, which uses search value to filter itself.