JavaScript technologies

Introducing Marionette in the example application

Horváth, Győző
senior lecturer
horvath.gyozo@inf.elte.hu

Financed from the financial support ELTE won from the Higher Education Restructuring Fund of the Hungarian Government

Task

Rewrite the example application with Marionette!

Installation

  1. bower install backbone.marionette --save
  2. Reference in the index.html

Templates

<script type="text/template" id="filter-template">
    <form class="form-inline">
        <div class="form-group">
            <label for="text-filter">Filter</label>
            <input type="text" class="form-control" id="text-filter">
        </div>
    </form>
</script>

<script type="text/template" id="list-item-template">
    <%= title %>
</script>

RootView

var RootView = Marionette.LayoutView.extend({
    el: 'body',
    regions: {
        'main': '#main'
    }
});

ListContainerView

var ListContainerView = Marionette.LayoutView.extend({
    
    el: '#list-container',
    template: false,

    regions: {
        filter: '#filter',
        list:   '#list',
    },

    onBeforeShow() {
        this.getRegion('filter').show(new FilterView());
        this.getRegion('list').show(new ListView({
            collection: this.collection
        }));
    }
});

FilterView

var FilterView = Marionette.ItemView.extend({
    template: '#filter-template',
});

ListView

var ListView = Marionette.CollectionView.extend({
    tagName: 'ul',
    className: 'list-group',
    childView: ListItemView
});

ListItemView

var ListItemView = Marionette.ItemView.extend({
    tagName: 'li',
    className: 'list-group-item',
    template: '#list-item-template',
});

Application

var app = new Marionette.Application();
        
app.on('start', function () {
    this.rootView = new RootView();
    this.lcv = new ListContainerView({
        collection: new CodeSnippetCollection(snippets)
    });
    this.rootView.getRegion('main').show(this.lcv);
});

app.start();

Filtering 1.

FilterView

var FilterView = Marionette.ItemView.extend({
    template: '#filter-template',
    ui: {
        'filterInput': '#text-filter'
    },
    events: {
        'keyup @ui.filterInput': 'onFilter',
        'submit': 'onSubmit',
    },
    onFilter(e) {
        var filterText = this.ui.filterInput.val();
        //console.log(filterText);
        this.trigger('filter:change', filterText);
    },
    onSubmit(e) {
        e.preventDefault();
    }
});

Filtering 2.

var ListContainerView = Marionette.LayoutView.extend({
    
    initialize() {
        this.filterView = new FilterView();
        this.collection = makeFilteredCollection(this.collection, function (filterText) {
            return this.filter(function (sn) {
                return sn.get('title').indexOf(filterText) > -1;
            });
        });
        this.collection.doFilter('');
                
        //this.filterView.on('filter:change', ...);
        this.listenTo(this.filterView, 'filter:change', this.updateCollection);
    },

    onBeforeShow() {
        this.getRegion('filter').show(this.filterView);
        this.getRegion('list').show(new ListView({
            collection: this.collection
        }));
    },

    updateCollection: function (filterText) {
        this.collection.doFilter(filterText);
    }

});

Filtering 3.

Helper function

function makeFilteredCollection(coll, filterFn) {
    var FC = Backbone.Collection.extend({
        initialize: function () {
            filterFn = filterFn.bind(coll);
        },
        doFilter: function (filterText) {
            var filtered = filterFn(filterText);
            return this.reset(filtered);
        }
    });
        
    return (new FC());
}

Feladat

Decompose the application into modules!

Use browserify for bundling, and gulp for running the task!

1. step

index.html

<script src="dist/bundle.js"></script>

2. step

Module decomposition: import, export

  1. Models
  2. Collections
  3. Views
  4. Application
  5. main
import Backbone from 'backbone';

export default Backbone.Model.extend({
    defaults() {
        return { /*...*/ };
    },
});