AniAko
AniAko

Reputation: 149

backbone.js this.[method] is not a function

I'm having an issue with a helper function inside my Backbon.js View. When it's run, it dies with the following error message about the first line of the "addCalc" function:

TypeError: this.getCalcValue is not a function

It's really puzzling because in the "initialize" function defined just above, all the functions seem to be defined. It feels like I'm calling the sibling method wrong, and the "initialize" method is an exception where "this" can be used to reference the object.

Is there something wrong/missing with the following code, or something I missed with the backbone documentation?

CalcView = Backbone.View.extend({
    el: $("#calcView"),
    initialize: function () {
        this.resetCalc();
    },

    addCalc: function (model) {
        var cost = this.getCalcValue(model.get('currentCost'));
        var custom = this.getCalcValue(model.get('customProgram'));

        var variables = { id: model.get('id'),
                category: model.get('category'),
                shortDesc: model.get('shortDescription'),
                description: model.get('description'),
                currentCost: cost,
                customProgram: custom,
        };

        var template = _.template($('#calc_template').html(), variables);
        $("#calc_payload").append(template);
    },

    resetCalc: function(models) {
        $("#calc_payload tr").remove();
    },

    removeCalc: function(model){
        $("#calc_payload #" + model.get('id')).remove();
    },

    updateCalcs: function(model) {

        var cost = model.get('currentCost');
        var custom = model.get('customProgram');

        $("#" + model.get("id") + " .currentCost").text(this.getCalcValue(cost));
        $("#" + model.get("id") + " .customProgram").text(this.getCalcValue(custom));

        /*var currentCostSum = 0;
        var customProgramSum = 0;
        $("#calc_payload .currentCost").each(function() {
            var temp = Number(($(this).text()).replace(/[^0-9\.]+/g, ""));
            if (!isNaN(temp))
                    currentCostSum += temp;
        });

        $("#calc_payload .customProgram").each(function() {
            var temp = Number(($(this).text()).replace(/[^0-9\.]+/g, ""));
            if (!isNaN(temp))
                customProgramSum += temp;
        });

        $("#calc_footer .currentCost").text("$" + ((currentCostSum == 0) ? " -- " : CurrencyFormatted(currentCostSum.toFixed(2))));
        $("#calc_footer .customProgram").text("$" + ((customProgramSum == 0) ? " -- " : CurrencyFormatted(customProgramSum.toFixed(2))));*/
    },

    getCalcValue: function(value) {
        if (typeof value == 'string' || value instanceof String)
            return value.toString();
        else if (isNaN(value))
            return "$ -- ";
        else
            return "$" + value.toFixed(2); 
    },                  
});

The code that executes the "addCalc" function is driven by a backbone collection. Basically, when the collection is added to, the CalcView.addCalc is called

Calculations = Backbone.Collection.extend({
    model: Calculation,
    //This is our Friends collection and holds our Friend models
    initialize: function (models, options) {
        this.on("add", options.onAdd);
        this.on("remove", options.onRemove);
        this.on("reset", options.onReset);
        //Listen for new additions to the collection and call a view function if so
    }
});


//This is where addCalc is used.
var calcview = new CalcView();
var calc_collection = new Calculations( null, { 
    onAdd: calcview.addCalc, 
    onRemove: calcview.removeCalc, 
    onReset: calcview.resetCalc 
});

Upvotes: 0

Views: 2420

Answers (2)

Niranjan Borawake
Niranjan Borawake

Reputation: 1638

When you bind events on collection you can send the context as third argument. Try sending one more option property as your calcview and pass it as context.

this.on("add", options.onAdd, options.calcview);
this.on("remove", options.onRemove, options.calcview);
this.on("reset", options.onReset, options.calcview);

Upvotes: 0

Ed_
Ed_

Reputation: 19098

In your initialize function add this line of code:

_.bindAll(this,'addCalc');

This will bind this to be your CalcView for the addCalc function. You can put multiple comma separated method names in there if you need to bind more than one function...

See Underscore's documentation on it here.

Upvotes: 2

Related Questions