Backbone passing a view an event and unbinding it from parent view

200 views Asked by At

I was wondering if it is possible to pass a view en event, and then stop that event running again until another method has been run?

This is my setup,

Main View Method

changeAdmin: function(e) {

    var element = $(e.currentTarget),
        userID = element.data('user'),
        is_admin = (element.is(':checked')) ? 1 : 0,
        confirmMsg = (element.is(':checked')) ? 'Adding administration rights to this user will add them to all of ' + this.model.get('name') + '\'s projects.' : 'Removing administration rights from this user will remove them from all of ' + this.model.get('name') + '\'s projects.';

    var notify = new App.Views.ConfirmationView({
        message: confirmMsg,
        confirm_callback: function(){

        },
        fail_callback: function() {

        },
        vent: e

    });

    notify.render();

    var user = this.model.get('members').get(userID);
    user.get('pivot').is_admin = is_admin;
    user.set('admin', is_admin);

    console.log(user.get('pivot'));


},

Child View

    'use strict'
App.Views.ConfirmationView = Backbone.View.extend({

    tagName: 'div',
    className: 'notification alert alert-warning',

    template: _.template( $('#tpl-cofirmation').html() ),

    events: {
        "click .js-confirm" : "runSuccessCallback",
        "click .js-cancel": "runFailCallback"
    },

    initialize: function(options) {
        this.options = options;
        this.confirm = options.confirm_callback;
        this.fail = options.fail_callback;
    },


    render: function() {
        //var self = this;
        this.$el.html(this.template({
            message: this.options.message
        })).css({
            'z-index':'9999',
            'position':'absolute', 
            'padding':'10px',
            'left':'50%',
            'top' : '0px',
            'transform': 'translate(-50%, 0px)'
        }).animate({
            'top' : '150px'
        }, 500, 'easeOutExpo').prependTo('body');

    },

    cancel: function() {
        this.$el.hide();
    },

    confirm: function() {
        this.$el.hide();
    },

    runSuccessCallback: function(){

       this.confirm();
       $.when(this.$el.animate({
        'top' : '-150px'
       }, 500, 'easeOutExpo').promise()).done(function(){
        this.remove();
       });
    },

    runFailCallback: function(){
       this.fail();
       $.when(this.$el.animate({
        'top' : '-150px'
       }, 500, 'easeOutExpo').promise()).done(function(){
        this.remove();
       });

    }

});

On the child view render I want to disable the event that is passed and then on fail() or success() reactivate it is this possible?

1

There are 1 answers

0
thataustin On

I'm going to make an assumption here. I'm guessing that what you're really getting at is that you don't want to allow the notify.render() to be triggered from the parent multiple times in a row unless one of the callbacks has been called in between. On that assumption, I don't think the child view should be the one to quit listening. You need to temporarily disable whatever the events in the parent view that call changeAdmin. I think putting that in the child view intertwines the two more than you need (breaking SoC principles IMO).

That said, I'd consider using http://backbonejs.org/#View-undelegateEvents (eg, this.undelegateEvents() in the parent view before rendering the child view and re-enabling the events in the callback like so:

changeAdmin: function(e) {

    var self = this;
    this.undelegateEvents();


    var confirm_callback = function() {
        // do confirm stuff

        // re-enable events at the bottom of this callback
        self.delegateEvents();
     };

     var notify = new App.Views.ConfirmationView({
        confirm_callback: confirm_callback,
     });

     notify.render();
}

I removed some of the parts of your code not pertinent to the explanation, but hopefully you get the idea. And you'd do a similar thing for the fail_callback.