Search code examples
backbone.jsbackbone-viewsbackbone-events

reuse Bootsrap Modal view in BackboneJS


I just started to learn BackboneJS and getting deeper inside I face a problem. I have a bootstrap modal where I would like populate the modal-content in function of a called event fired in my main view and try to figure out how to inject a subview in my Modal view which is dynamically generated. So far my code looks like but not working

Main view

//here events are mapped
    Fefe.Views = Fefe.Views || {};

    (function () {
        'use strict';

        Fefe.Views.Editor = Backbone.View.extend({

            template: JST['app/scripts/templates/editor.ejs'],

            tagName: 'div',

            el: '.container',

            id: '',

            className: '',

            events: {

                "click button.expand" : "controlToggle",
                "click .grid" : "grid"
            },


            controlToggle: function(e){
                var controlls =  $(e.currentTarget).closest('.editor-controls')

                $(controlls).find('.active').removeClass('active')
                $(e.currentTarget).parent().addClass('active')
            },

            grid: function() {

                this.model = new Fefe.Models.Grids({
                    'title': 'Edit Grids'
                })

                var gridView = new Fefe.Views.Grids({
                    model: this.model 
                })

                var grids = new Fefe.Views.Modal({
                    model : this.model,
                    subview: gridView
                }).render()

            },

            initialize: function () {
                var body = $('body')
                var rows = body.find('.row')

                $.each(rows, function(e , v){

                    $(this).addClass('editor-row empty-row')

                })

            $('.sortable-rows').sortable({ handle: 'button.row-handle.btn.btn-default' })
                this.listenTo(this.model, 'change', this.render);
            },

            render: function () {

                return this;
            }

        });

    })();

Modal view

//this one holds the modal markup

    Fefe.Views = Fefe.Views || {};

    (function () {
        'use strict';

        Fefe.Views.Modal = Backbone.Marionette.View.extend({

            template: JST['app/scripts/templates/modal.ejs'],

            subview: '',

            className: "modal",
            attributes: {
                tabindex: "-1",
                role: "dialog",
            },

            initialize: function() {          

              this.template = this.template;
              console.log(this)

            },

          events: {
              "click .save": "save",
              "click .close": "close",
              "change input": "modify",
            },

        render: function(e) {

            this.$el.html(this.template(this.model.toJSON())).modal()

            $(".modal-dialog").draggable({
                  handle: ".modal-header"
            })

            return this
        },

        show: function() {
            $(document.body).append(this.render().el);

        },

        close: function() {
            this.remove();
        },

        save: function() {
            if(this.model.id == null) {
              tasks.create(this.model);
          }
          else {
              this.model.save();
          }
          this.remove();
      },

      edit: function(e) {
        var attribute = {};

        attribute[e.currentTarget.name] = e.currentTarget.value;
        this.model.set(attribute);
    },

    });

    })();

Maybe the approach is wrong and I'm on the wrong track


Solution

  • You should checkout the way with custom regions, described by Brian Mann at backbonerails.com

    So the idea is following:

    1) Define a region in your app with special class, lets call it DialogRegion

    regions: {
        dialogs: {
            selector: '#dialogs',
            regionClass: DialogRegion
        }
    }
    

    2) Extend DialogRegion like following. I used Bootstrap modal API, please expect

    var DialogRegion = Marionette.Region.extend({
        onShow: function(view) {
            view.$el.addClass('modal');
            view.$el.modal();
    
            // add handler to close popup via event
            view.on('before:destroy', function() {
                view.$el.modal('hide');
            });
    
            //destroy view on popup close
            view.$el.on('hidden.bs.modal', function (e) {
                view.destroy();
            });
        })
    })
    

    3) Later from any place of your app you can render Modal via rendering any view in dialogs App region:

    App.dialogs.show( new SomeSuperView({
        model: model
    }))
    

    I recommend you to checkout tutorial at Backbonerails to clarify this way. Hope you will find it usefull