Kianosh
Kianosh

Reputation: 179

Backbone events firing multiple times even though I am following proper standards

I have a table that when I click on a row, in a side div I display the details. I have created an event on the row (tr) that is fired every time that row is clicked. The problem I have is that the event is being fired multiple times. It is acting as if a new view is being created everytime the event is fired, but a new view is not being created. Here is the code:

GroupView = class App.GroupView extends Backbone.View
    template: App.Utils.getTemplate 'group'
    selectedId: 0

    events:
        'click tr': 'selectGroup'

    selectGroup: (e) ->
        thisEl = $(e.currentTarget)
        $(thisEl).closest('tr').siblings().removeClass 'selected'
        $(thisEl).closest('tr').addClass 'selected'
        @selectedId = $(thisEl).data().id
        @getGroupDetails @selectedId

    render: -> 
        $(@$el).html @template
            groups: @collection.models

        if @selectedId is 0
            firstRowEl = $(@$el).find('tr:first')
            $(firstRowEl).addClass 'selected'
            @selectedId = $(firstRowEl).data().id

        @getGroupDetails @selectedId

    getGroupDetails: (id, platform) ->
        $('<img/>', 
            src: 'img/ajax_loader_2.gif'
            class: 'ajax-loader'
            ).appendTo '.group-details'

        renderGroupDetails id

groupDetails = new GroupDetailsView
    el: '.group-details'
    model: groupDetailsModel

renderGroupDetails = (id)->
    groupDetails.el = '.group-details'
    groupDetails.stopListening groupDetailsModel
    groupDetails.listenTo groupDetailsModel, 'change', ->
    groupDetails.model = 
        groupDetails: groupDetailsModel.toJSON()
    groupDetails.render()

    groupDetailsModel.fetch
        data:
            id: id
        processData: true

The issue is that when I use the groupDetails.stopListening groupDetailsModel, the multiple event firing issue is resolved but then NONE of the events in the groupDetails view is being fired.

Any help is appreciated.

Cheers,

Kianosh

Upvotes: 0

Views: 903

Answers (1)

machineghost
machineghost

Reputation: 35735

So, giving you a specific answer is difficult: the code you've pasted is a bit hard to follow, and seems like it might be missing bits (eg. what's a groupDetailsModel? Does it have any logic that affects it's view?). That's ok though, because I think what you need here is more debugging help than a specific answer.

If I understand you correctly, your problem is that groupDetails.render() is being invoked extra times, and you're not sure why or what is invoking it: is that correct? If so, your trusty debugger can answer this in a matter of seconds.

NOTE: Everything I'm about to say applies to Chrome (with the built-in developer tools up) or Firefox (with the Firebug extension up) for sure. It probably applies to other browsers with their tools too, I just can't say for sure since I don't use them.

Approach #1: Debugger

With your debugger up, add a debugger; line as the first thing inside your GroupDetails.prototype.render method. This will make your browser pause on that line whenever it hits it. While its paused you can check the "call stack" on the right-hand side, and that will show you exactly what bit of your code just called that render. You can also use the debugger to inspect the values of the different variables in your environment to try and understand why your code is calling render.

Approach #2: Console.trace

If you're not a fan of using the debugger, there's another tool that's also perfect for answering this sort of question. Simply add console.trace() as the first line in your render method, then run your code as normal. This time your browser will log (to the "console") a stack trace generated from that point in the code. This stack trace is similar to the call stack that you can see when you use debugger, and thus it will tell you exactly what code invoked the render each time.

Hope that helps.

Upvotes: 3

Related Questions