2

I have a bunch of checkboxes that represent filters, so when clicking a checkbox it should add an object containing the type of filter (taxonomy) and the value (terms) to a filter array.

When clicking the checkbox it first adds a new object containing a taxonomy and terms property. So far this works. The problem is when i click a third checkbox that has an taxonomy value that already exists, it adds a whole new object to the array instead of adding the term to the already existing term array.

This is what it looks like right now:

<input type="checkbox" id="term-1" value="term-1" name="taxonomy-1">
<label for="term-1">Term 1</label>

<input type="checkbox" id="term-2" value="term-2" name="taxonomy-1">
<label for="term-2">Term 2</label>

<input type="checkbox" id="term-3" value="term-3" name="taxonomy-1">
<label for="term-3">Term 3</label>

File1.js

import FilterModule from '../helpers/filter-module';

class View {
    constructor() {
        self.filterModule = new FilterModule();
        this.$filters = $( '[data-filters]' );
    }
    
    // Called after api got data
    update() {
        // Set event listener for select(s)
        this.$filters.find( 'select' ).on( 'change', this.handleFiltering );
        this.$filters.find( 'input[type="checkbox"]' ).on( 'change', this.handleFiltering );
    }

    handleFiltering() {
        let tax = $( this ).attr( 'name' );
        const term = $( this ).val();
        self.filterModule.handleCheckbox( $( this ), tax, term );
    }
}

export default new View();

File2.js

import Api from '../helpers/api';

export default class FilterModule {
    handleCheckbox( checkbox, tax, term ) {
        const filters = Api.response.filters.active_filters;

        if ( $( checkbox ).is( ':checked' ) ) {

            // Check if taxonomy exists, if not, add it
            const index = filters.findIndex( x => x.taxonomy === tax );
            if ( index === -1 ) {
                console.log( 'does not exist, add new taxonomy object' );

                // Add new selection
                filters.push( {
                    taxonomy: tax,
                    terms: [ term ]
                } );
            } else {
                console.log( 'tax exists, push new term into it' );
                filters.find( x => x.taxonomy === tax ).terms.push( term );
            }

            console.log( filters );

        }

        // Update data
        this.update();
    }

    update() {
        Api.fetch();
    }
}

So the first checkboxes click works well, the result would be:

{
   taxonomy: 'taxonomy-1',
   terms: [ 'term-1' ]
}

Second click:

{
   taxonomy: 'taxonomy-1',
   terms: [ 'term-1', 'term-2' ]
}

But the third click results in:

{
   taxonomy: 'taxonomy-1',
   terms: [ 'term-1', 'term-2' ]
},
{
   taxonomy: 'taxonomy-1',
   terms: [ 'term-3' ]
},

I don't understand why a new object is added instead of pushing it to the terms array of the taxonomy that exists.

5
  • 2
    Can you provide enough context to reproduce the issue? (HTML? the way the function is called?) Commented Sep 14, 2020 at 7:06
  • How does handleCheckbox get called? When you say "third click", do you mean it always happens no matter which checkbox is clicked as third, or is it the same checkbox each time? Commented Sep 14, 2020 at 7:07
  • I've added some (simplified) more code. @RoToRa this happens on the same checkbox Commented Sep 14, 2020 at 7:18
  • In handleFiltering you are reading the taxonomy from the id, but in the HTML it's in the name. Due to in the incomplete code it's a bit difficult to determine what this is. A complete working snippet would make the debugging easier. Inside the event handler it probably be a good idea to use target from the event object instead of this. Commented Sep 14, 2020 at 7:27
  • Yes sorry, i updated my question again. Commented Sep 14, 2020 at 7:39

1 Answer 1

3

I created a workable example of your code, but changed the let tax = $(this).attr('id') to let tax = $(this).attr('name');.

So far, everything works as you expect, terms are added to the existing object instead of a new object being created:

$('input[type="checkbox"]').on('change', this.handleFiltering);

const activeFilters = [];

function handleFiltering() {
    let tax = $(this).attr('name');
    const term = $(this).val();

    handleCheckbox($(this), tax, term);
}


function handleCheckbox(checkbox, tax, term) {

    // activeFilters represents an array
    if ($(checkbox).is(':checked')) {

        // Check if taxonomy exists, if not, add it
        const index = activeFilters.findIndex(x => x.taxonomy === tax);
        if (index === -1) {
            console.log('does not exist, add new object');

            // Add new selection
            activeFilters.push({
                taxonomy: tax,
                terms: [term]
            });
        } else {
            console.log('tax exists, push new term into it');
            activeFilters.find(x => x.taxonomy === tax).terms.push(term);
        }

    }
    
    output.innerHTML = JSON.stringify(activeFilters, null, 2);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="checkbox" id="term-1" value="term-1" name="taxonomy-1">
<label for="term-1">Term 1</label>

<input type="checkbox" id="term-2" value="term-2" name="taxonomy-1">
<label for="term-2">Term 2</label>

<input type="checkbox" id="term-3" value="term-3" name="taxonomy-1">
<label for="term-3">Term 3</label>

<pre id="output"></pre>

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

1 Comment

Thanks. My code seemed to work all along, the problem was the API not returning the data correctly!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.