azz0r
azz0r

Reputation: 3311

Shared Marionette vent.on across different views

Hello I have a layout view that has many filter partials and a collection. filter partials are shared across my project so they all reference "filter:change" as there trigger.

However, I am finding that when I change page and cause a "filter:change" I get issues with the previous view vent binds being called (and by then the template is removed from the dom).

Basically, when my my layout view closes I need to unbind the event "filter:change" so that the next layoutview can exclusively access that trigger.

Current code:

define([
  "text!app/templates/users/index.html",
  'app/views/users/collection',
  'app/views/users/partials/internal',
  'app/views/users/partials/enabled',
  'app/views/partials/location_id'
],
  function(Template, CollectionView, FilterInternalView, FilterEnabledView, FilterLocationIdView) {
    "use strict"

    return Backbone.Marionette.Layout.extend({


      template: Template,


      regions: {
        filterInternal: '#filterInternalContainer',
        filterEnabled: '#filterEnabledContainer',
        filterLocationId: '#filterLocationIdContainer',

        collectionLatch: '#collectionLatch'
      },


      initialize: function() {

        // horrible scope issues with javascript
        var that = this;

        // if the filter change event is triggered in a sub view
        MyApp.vent.on('filter:change', function() {
          // fetch the collection and pass its filters through
          that.renderCollection(that.getFilter());
        })
      },


      getFilter: function() {

        // create our new filter object using jQuery picking the values
        var filter = {
          from: "0",
          to: parseInt(100),
          enabled: $('#filterEnabled').val(),
          internal: $('#filterInternal').val(),
          location_id: $('#filterLocationId').val()
        };

        // passing it through a null stripper
        filter = _.cleanNullFieldsFromObject(filter);

        // set the filter object to local storage (extended, not typical)
        localStorage.setObject('userFilter', filter);

        return filter;
      },


      renderFilterEnabled: function(options) {
        this.filterEnabled.show(new FilterEnabledView(options));
      },


      renderFilterInternal: function(options) {
        this.filterInternal.show(new FilterInternalView(options));
      },


      renderFilterLocationId: function(options) {
        this.filterLocationId.show(new FilterLocationIdView(options));
      },


      renderCollection: function(options) {
        // render the post list
        this.collectionLatch.show(new CollectionView(options));
      },


      onRender: function () {

        // do we need to over write the filter object from local storage?
        var userFilter = localStorage.getObject('userFilter');

        // if local storage isn't empty then over ride the filter with it
        if (!_.isEmpty(userFilter)) {
          this.filter = userFilter;
        } else {
          this.filter = this.getFilter();
        }

        // render the filters on our page
        this.renderFilterEnabled(this.filter);
        this.renderFilterInternal(this.filter);
        this.renderFilterLocationId(this.filter);

        // render the collection
        this.renderCollection(this.filter);
      },


      onClose: function() {}


    })
  })

// partial view

define(["marionette", "text!app/templates/partials/location_id.html", 'app/models/location'],
  function(Marionette, Template, Model) {
    "use strict"
    return Backbone.Marionette.ItemView.extend({
      template: Template,


      events: {
        'change #filterLocationId': 'onFilter'
      },


      initialize: function(options) {
        this.value = _.isEmpty(options) ? '-' : options.location_id;
      },


      onFilter: function() {
        MyApp.vent.trigger('filter:change');
      },


      serializeData: function() {
        return {values: new Model().getIds(), value: this.value};
      }


    })
  })

I looked at the documentation: https://backbonemarionette.readthedocs.org/en/latest/marionette.eventbinder.html#unbind-a-single-event

and tried:

  onClose: function() {
    MyApp.vent.off('filter:change');
  }

but no matter what, even if the next view turns that vent back on, the event doesn't work.

Upvotes: 0

Views: 421

Answers (1)

Rida BENHAMMANE
Rida BENHAMMANE

Reputation: 4129

Try to change the :

MyApp.vent.on('filter:change', function() {
    // fetch the collection and pass its filters through
    that.renderCollection(that.getFilter());
})

by

this.listenTo(MyApp.vent, 'filter:change', function() {
    // fetch the collection and pass its filters through
    that.renderCollection(that.getFilter());
})

Upvotes: 1

Related Questions