JavaScript technologies

Communication between modules in the extended 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

Extend the application with the following features: selecting a code snippet in the list we may view the details of the selected snippet. Furthermore editing, deleting and returning to the list page is also needed.

Use the Backbone.Radio module for communicating between the larger parts of the application!

1. step

index.html

<div id="main-container">
    <h1>Kódlista</h1>
    <div id="main"></div>
</div>

<script type="text/template" id="list-container-template">
    <div id="filter"></div>
    <div id="list"></div>
</script>

<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>

<script type="text/template" id="snippet-container-template">
    <div id="nav"></div>
    <div id="snippetView"></div>
    <div id="snippetEdit"></div>
</script>

<script type="text/template" id="snippet-view-template">
    <h2><%= title %></h2>
    <pre>
<%= code %>
    </pre>
</script>

<script type="text/template" id="navigation-template">
    <div class="btn-group" role="group">
        <button type="button" class="btn btn-default" id="snippet-view">View</button>
        <button type="button" class="btn btn-default" id="snippet-edit">Edit</button>
        <button type="button" class="btn btn-default" id="snippet-delete">Delete</button>
        <button type="button" class="btn btn-default" id="snippet-back">Back</button>
    </div>
</script>

<script type="text/template" id="snippet-edit-template">
    Title: <input type="text" value="<%= title %>" class="form-control" id="snippet-title">
    Snippet: <br>
    <textarea class="form-control" id="snippet-code"><%= code %></textarea>
    <input type="button" value="Save" class="form-control btn btn-primary" id="snippet-save">
</script>

2. step

ListItemView

var mainChannel = Radio.channel('main');

export default Marionette.ItemView.extend({
    /* ... */
    events: {
        'click': 'onClick'
    },
    onClick: function (e) {
        // console.log(this.model);
        mainChannel.trigger('snippet:selected', this.model);
    }
});

3. step

Application

var app = new Marionette.Application({
    showSnippet: function (data) {
        console.log(data);
        // this.rootView.getRegion('main').show(new SnippetContainerView({
        //     model: data
        // }));
    },
});

app.on('start', function () {
    this.listenTo(mainChannel, 'snippet:selected', this.showSnippet);
})

4. step

SnippetContainerView

export default Marionette.LayoutView.extend({
    template: '#snippet-container-template',
    regions: {
        'nav': '#nav',
        'snippet': '#snippet',
    },
    initialize: function () {
        // this.snippetViewView = new SnippetViewView({
        //     model: this.model
        // });

        // this.navigationView = new NavigationView();

        // this.snippetEditView = new SnippetEditView({
        //     model: this.model
        // });
    },
    onBeforeShow: function () {
        // this.getRegion('snippetView').show(this.snippetViewView);
        // this.getRegion('nav').show(this.navigationView);
        // this.getRegion('snippetEdit').show(this.snippetEditView);  
    }
});

5. step

SnippetViewView, NavigationView, SnippetEditView

// SnippetViewView
export default Marionette.ItemView.extend({
    template: '#snippet-view-template',
});

// NavigationView
export default Marionette.ItemView.extend({
    template: '#navigation-template',
});

// SnippetEditView
export default Marionette.ItemView.extend({
    template: '#snippet-edit-template',
    tagName: 'form',
});

6. step

SnippetViewView, SnippetEditView

initialize: function () {
    this._hide();
},
_show: function () {
    this.$el.show();
},
_hide: function () {
    this.$el.hide();
}

7. step

NavigationView

ui: {
    'snippetBack': '#snippet-back',
    'snippetEdit': '#snippet-edit',
    'snippetDelete': '#snippet-delete',
    'snippetView': '#snippet-view',
},
events: {
    'click @ui.snippetView': 'onClickView',
    'click @ui.snippetEdit': 'onClickEdit',
    'click @ui.snippetDelete': 'onClickDelete',
    'click @ui.snippetBack': 'onClickBack',
},
onClickView: function (e) {
    this.trigger('nav:viewSnippet');
},
onClickEdit: function (e) {
    this.trigger('nav:editSnippet');
},
onClickDelete: function (e) {
    this.trigger('nav:deleteSnippet');
},
onClickBack: function (e) {
    mainChannel.trigger('nav:back');
},

8. step

SnippetContainerView

initialize: function () {
    /* ... */
    this.listenTo(this.navigationView, 'nav:viewSnippet', this.onViewSnippet);
    this.listenTo(this.navigationView, 'nav:editSnippet', this.onEditSnippet);
    this.listenTo(this.navigationView, 'nav:deleteSnippet', this.onDeleteSnippet);
},
onEditSnippet: function () {
    this.snippetViewView._hide();
    this.snippetEditView._show();
},
onDeleteSnippet: function () {
    if (confirm("Delete snippet?")) {
        this.model.destroy();
        mainChannel.trigger('nav:back');
    }
},
onViewSnippet: function () {
    this.snippetEditView._hide();   
    this.snippetViewView._show();
},

9. step

SnippetEditView

ui: {
    'save': '#snippet-save',
    'title': '#snippet-title',
    'code': '#snippet-code'
},
events: {
    'click @ui.save': 'onSave'
},
onSave: function (e) {
    this.model.set({
        'title': this.ui.title.val(),
        'code':  this.ui.code.val()
    });
    this.trigger('snippet:saved');
},

10. step

SnippetContainerView

initialize: function () {
    /* ... */
    this.listenTo(this.snippetEditView, 'snippet:saved', this.onViewSnippet);
},

11. step

Application

var app = new Marionette.Application({
    /* ... */
    showSnippetList: function () {
        this.rootView.getRegion('main').show(new ListContainerView({
            collection: csc
        }));
    },
});
        
app.on('start', function () {
    /* ... */
    this.listenTo(mainChannel, 'nav:back', this.showSnippetList);
});