2

I have set ui elements referring to a class in my Marionette View, and I wonder if there is a way to get information on which element has precisely been clicked on. I usually use collections in that kind of cases, which allows to get the index of elements, but here it would be hard to set up. Here is an example with hard values.

View:

var QuoteView = Marionette.View.extend({
  template: quoteViewTpl,
  modelEvents: {
    'change': 'render'
  },
  ui:{
    'select_package': '.package'
  },
  triggers:{
    'click @ui.select_package': 'select:package'
  },
  onSelectPackage: function(){
    //how to know which element was selected?
  }
});

Template:

 <%for(prop in obj){%>
         <div class="col-xs-<%=Math.round(8/(Object.keys(obj).length-1))%>">
             <div class="quotation-rate-value package">
                 <%=obj.y%> € / year
             </div>
         </div>

 <%}%>

Model:

var Quote = Backbone.Model.extend({
    defaults:{
        obj: {
            assist: {
               y: 220,
               m: 18.33,
               d: 0.60
            },
            fire: {
               y: 330,
               m: 27.5,
               d: 0.90
            },
            loan: {
               y: 660,
               m: 54.99,
               d: 1.80
            },
            disability: {
               y: 440,
               m: 36.66,
               d: 1.20
            },
        } 
    }
});
Alex
  • 1,090
  • 7
  • 21

2 Answers2

1

The first argument passed to your onSelectPackage function is the event object. This object can be used to determine which element was selected. Ex:

...,

onSelectPackage: function(e) {
    var el = e.currentTarget; // .package element
},

...
lucasjackson
  • 1,515
  • 1
  • 11
  • 21
1

Use data-attribute

Put the property name in the rendered HTML.

<% for (var prop in obj) { %>
    <div class="col-xs-<%= Math.round(8/(Object.keys(obj).length-1)) %>">
        <div class="quotation-rate-value package" data-prop="<%= prop %>">
            <%= obj[prop].y %> € / year
        </div>
    </div>

<% } %>

Then using jQuery, get the data value.

onSelectPackage: function(e) {
    $(e.currentTarget).data('prop'); // 'assist', 'fire', etc.
},

Backbone way of handling list elements

If there's any interaction possible with an element of a list that is (or can be) represented by a model, each element should be a Backbone View.

Make a model that will handle the data:

var QuoteProperty = Backbone.Model.extend({
    defaults: {
        propName: 'assist',
        y: 0,
        m: 0, 
        d: 0
    }
});

Put each Quote properties in a collection:

var Quote = Backbone.Model.extend({
    defaults: function() {
        return {
            assist: { y: 220, m: 18.33, d: 0.60 },
            fire: { y: 330, m: 27.5, d: 0.90 },
            loan: { y: 660, m: 54.99, d: 1.80 },
            disability: { y: 440, m: 36.66, d: 1.20 },
        };
    },
    getPropertiesCollection: function() {
        return _.reduce(this.attributes, function(collection, values, key) {
            collection.push(_.extend({ propName: key }, values));
            return collection;
        });
    }
});

and render each model in a new element view. With Marionnette, there's the CollectionView and with vanilla Backbone, there are multiple example already available (here's one of mine).

In that element view, listen for clicks on the element you want.

var QuotePropertyElementView = Backbone.View.extend({
    template: _.template('<div class="quotation-rate-value package"><%= y %> € / year</div>'),
    events: {
        'click': 'onClick'
    },
    render: function() {
        this.$el.html(this.template(this.model.toJSON));
        return this;
    },
    onClick: function() {
        this.model.trigger('custom:click:event', this.model);
    }
});

Then in the original view, listen on the collection to handle events from properties.

var QuoteView = Marionette.View.extend({
    initialize: function() {
        this.listenTo(this.collection, 'custom:click:event', this.onSelectPackage);
    },
    // rendering logic with CollectionView or custom
    onSelectPackage: function(model) {
        // model.get('y');
    }
});
Community
  • 1
  • 1
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129