Alex Martin Alex Martin - 18 days ago 9
jQuery Question

scope of "this" changes when using grep in jquery widget

I have two groups of JSON data, one containing the data I want to filter down, and a second group representing the criteria for the filter.

The filter structure is pretty basic. It contains an Id of the element it's filtering on and it's value.

The other structure contains multiple fields, including the Id that relates back to the filter structure.

Both of these are stored in the global part of the widget. Normally, I would use this.filterData or this.jsonObjects to access them. However, if I try to filter using either grep, or the javascript array.filter function, then "this" changes, so I can't access the data anymore. Is there a way around this?

applyFilters: function() {
//var returnedData = $.grep(this.options.jsonObjects, this.grepFunction);
var returnedData = this.options.jsonObjects.filter(this.filterMatch);
filteredData = returnedData;
this.options.onFilterApply.call(this);
},

filterMatch: function(element) {
for(var key in this.filterData) {
if(this.filterData.hasOwnProperty(key)) {
for(var a = 0; a < this.filterData[key].values.length; a++) {
if(element[this.filterData[key].id]==this.filterData[key].values[a]) {
return true;
}
}
}
}
return false;
}


Hope this makes sense. During the applyFilters function, "this" represents the widget itself and it works fine. But as soon as it enters the filterMatch function, "this" becomes the window, so this.filterData is undefined. How can I access the filterData inside that function, or ultimately, what is the best way of filtering down a list of JSON objects?

Answer

You can save your scope in a variable before entering the filterMatch function. Something like :

var that = this;

    applyFilters: function() {
        //var returnedData = $.grep(this.options.jsonObjects, this.grepFunction);
        var returnedData = this.options.jsonObjects.filter(this.filterMatch);
        filteredData = returnedData;
        this.options.onFilterApply.call(this);
    },

    filterMatch: function(element) {
        for(var key in that.filterData) {
            if(that.filterData.hasOwnProperty(key)) {
                for(var a = 0; a < that.filterData[key].values.length; a++) {
                    if(element[that.filterData[key].id]==that.filterData[key].values[a]) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

You can bind your this to the function scope also.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Comments