1

Scratching my head over this...

I have a function called filterProducts that is called in my Angular 2 component anytime a user clicks a checkbox. For now, the method finds all checkboxes that are checked with a specific class name, gets their values, and then attempts to sort an array. Fairly simple...

// Called when any checkbox is checked or unchecked

filterProducts() {

// Grab all "Program" checkboxes that are checked
var programsToInclude = $(".programCheckbox:checkbox:checked").map(function () { return this.value; });

// If any "Program" checkboxes are checked, filter the list accordingly
if (programsToInclude)
    this.filteredProducts = this.filteredProducts.filter(x => programsToInclude.indexOf(x.programName) > -1);
}

Why am I getting the following error?

ORIGINAL EXCEPTION: TypeError: programsToInclude.indexOf is not a function

programsToInclude is definitely a string array, which should have this function, no?

1 Answer 1

3

programsToInclude isn't an array, it's a jQuery object. jQuery objects have a lot of array methods, but not all.

To get an array after using jQuery#map, you need to tack a .get() on the end:

var programsToInclude = $(".programCheckbox:checkbox:checked").map(function () { return this.value; }).get();
// ---------------------------------------------------------------------------------------------------^^^^
if (programsToInclude) { // <== This check is pointless, see below the fold for why
    this.filteredProducts = this.filteredProducts.filter(x => a.indexOf(x.programName) > -1);
}

Alternately, use get early to get a native array, which requires adjusting your filter call:

var programsToInclude = $(".programCheckbox:checkbox:checked").get().map(function(e) { return e.value; });
// -----------------------------------------------------------------^^^^----------^-----------^
if (programsToInclude) { // <== Again, see below the fold
    this.filteredProducts = this.filteredProducts.filter(x => programsToInclude.indexOf(x.programName) > -1);
}

In both cases, though, programsToInclude ends up being an array. If you want to use it as a jQuery object again later, you have to convert it back. If you do want to use it later, you might have the array separate:

var programsToInclude = $(".programCheckbox:checkbox:checked").map(function(e) { return e.value; });
if (programsToInclude) { // <== Same note
    let a = this.programsToInclude.get();
    this.filteredProducts = this.filteredProducts.filter(x => a.indexOf(x.programName) > -1);
}

Why the check is pointless: A jQuery object, even an empty one, is always truthy. If you want to check for an empty one, use if (obj.length). But there's not much point in such a check if you're about to do filter, filter is a no-op when the object is empty anyway.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.