Search code examples
javascriptjquerybackbone.js

Backbonejs View Self Template replaceWith and Events


I'm working on my first app using bbjs, after 10 tutorials and endless sources I am trying to come up with my code design.

I ask what is the best practice with views and templates. Also there is an events problem I am struggling with. As I understand, the view is to be responsible for one element and its contents (and other sub-views). For the code to be manageable, testable, etc.. the element/template is to be passed to the view on creation. In my app Imho the view should hold the templates, because the visible element has many "states" and a different template for each state. When the state changes, I guess its best to create a new view, but, is it possible for the view to update itself with new element?

App.Box = Backbone.Model.extend({
    defaults: function() {
        return {
            media: "http://placehold.it/200x100",
            text: "empty...",
            type: "type1"
        };
    }
});


App.BoxView = Backbone.View.extend({
    template: {},
    templates: {
            "type1": template('appboxtype1'),
            "type2": template('appboxtype2')
    },
    events: {
      'click .button': 'delete'
    },
    initialize: function(options) {
        this.listenTo(this.model, 'change', this.render);
        this.listenTo(this.model, 'destroy', this.remove);

        this.render();
    },

    render: function() {
        this.template = this.templates[ this.model.get("type") ];

        // first method
        this.$el.replaceWith(  $($.parseHTML(this.template(this)))  );
        this.$el.attr("id", this.model.cid);

        // second method
        var $t_el = this.$el;
        this.setElement( $($.parseHTML(this.template(this))) );
        this.$el.attr("id", this.model.cid);
        $t_el.replaceWith(  this.$el  );
        this.delegateEvents();

        //$('#'+this.model.cid).replaceWith(  $(g.test.trim()) );


        //! on the second render the events are no longer bind, deligateEvents doesn't help


        return this;
    },

    // get values
    text: function() { return this.model.get('text');  },
    media: function() { return this.model.get('media');  },
    delete: function() {
        this.model.destroy();
    }
});

Thanx! :)


Solution

  • I came up with this solution: http://jsfiddle.net/Antonimo/vrQzF/4/

    if anyone has a better idea its always welcome!

    basically, in view:

            var t_$el = this.$el;
            this.$el = $($.parseHTML(this.template(this)));
            this.$el.attr("id", this.cid);
            if (t_$el.parent().length !== 0) { // if in dom
                this.undelegateEvents();
                t_$el.each(function(index, el){ // clean up
                    if( index !== 0 ){ $(el).remove(); }
                });
                t_$el.first().replaceWith(this.$el);
                this.delegateEvents();
            }