Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trigger function on click if View has a certain class (backbone.js)

I have a div generated by a backbone.js view. When the user clicks on this div, a class active is added to the div and the function addToSet is executed.

Problem: I want another function to be triggered when the View's div has the class active. However, my attempt shown below always cause addToSet function to run when its clicked.

Now, I remove 'click': 'addToSet' from the events function, leaving only 'click .active': 'removeFromSet'. Clicking on the div does not cause anything to happen! Is this because the event handler cannot select the div of the view itself, just the elements inside it?

Any idea how I can solve this problem? Thanks!

JS Code

SetView = Backbone.View.extend({
    tagName: 'div',
    className: 'modal_addit_set',

    template: _.template( $('#tpl_modal_addit_set').html() ),

    events: {
        'click': 'addToSet',
        'click .active': 'removeFromSet'
    },

    initialize: function(opts) {
        this.post_id = opts.post_id;
    },

    render: function() {
        $(this.el).html( this.template( this.model.toJSON() ) );
        if(this.model.get('already_added'))
            $(this.el).addClass('active');
        return this;
    },

    addToSet: function() {
        $.post('api/add_to_set', {
            post_id: this.post_id,
            set_id: this.model.get('id'),
            user_id: $('#user_id').val()
        });
    },

    removeFromSet: function() {
        $.post('api/remove_from_set', {
            post_id: this.post_id,
            set_id: this.model.get('id')
        });
    }
});
like image 285
Nyxynyx Avatar asked Jan 16 '23 00:01

Nyxynyx


2 Answers

Have you tried to use a :not(.active) selector for one of your event delegates? This may help differentiate between the two scenarios.

Something like this:

events: {
   'click :not(.active)' : callback1
   'click .active' : callback2
}
like image 60
GreatTall1 Avatar answered Jan 25 '23 22:01

GreatTall1


These events:

events: {
    'click': 'addToSet',
    'click .active': 'removeFromSet'
}

don't work and you sort of know why. From the fine manual:

Events are written in the format {"event selector": "callback"}. The callback may be either the name of a method on the view, or a direct function body. Omitting the selector causes the event to be bound to the view's root element (this.el).

So your 'click': 'addToSet' binds addToSet to a click on the view's el itself but 'click .active': 'removeFromSet' binds removeFromSet to a .active element inside the view's el.

I think the easiest solution is to have a single event:

events: {
    'click': 'toggleInSet'
}

and then:

toggleInSet: function() {
    if(this.$el.hasClass('active')) {
        $.post('api/remove_from_set', {
            post_id: this.post_id,
            set_id: this.model.get('id')
        });
    }
    else {
        $.post('api/add_to_set', {
            post_id: this.post_id,
            set_id: this.model.get('id'),
            user_id: $('#user_id').val()
        });
    }
}

You could use an instance variable instead of a CSS class to control the branching in toggleInSet if that makes more sense.

like image 40
mu is too short Avatar answered Jan 25 '23 22:01

mu is too short