2

I would like get the checkbox status from store. I made a Comparison with the checkbox list and "active checkbox" list ( inArray(checkList.value, activeFilters) ), but I can't get the value from this.$store.getters.updateFilters. Here the code:

 <template>
    <li class="dropdown-child">
        <label >
            <input
                type="checkbox"
                :name="checkList.id"
                :value="checkList.name"
                :checked="inArray(checkList.value, activeFilters)"
                @change="updateFilter"
                >
            <span>{{ checkList.name }}</span>

        </label>
    </li>
</template>


<script>

    export default {
        props: ['checkList'],
        computed: {

            inArray (filterValue, filterChecked) {
                const intComparison = /^[+-]?\d+$/.test(filterValue)
                for (let i = 0, l = filterChecked.length; i < l; i++) {
                    if ((intComparison && parseInt(filterChecked[i], 10) === parseInt(filterValue, 10)) || (filterChecked[i] === filterValue)) {
                        return true
                    }
                }
                return false
            },

            activeFilters(){
                return this.$store.getters.updateFilters;
            }
        },
        methods: {

            updateFilter (evt) {
                const elm = evt.target || evt.srcElement
                const action = elm.checked === false
                    ? this.removeFilter(elm) //elm.checked
                    : this.addFilter(elm)
                const value = /^[+-]?\d+$/.test(elm.value)
                    ? parseInt(elm.value)
                    : elm.value
            },

            addFilter(elm){
                this.$store.dispatch('addFilter', elm);
            },

            removeFilter(elm){
                this.$store.dispatch('removeFilter', elm);
            }

        }
    }
</script>
4
  • Because you are referencing activeFilters instead of activeFilterList? Commented Jun 28, 2017 at 11:04
  • @Terry Sorry, was the old code, now it is correct code Commented Jun 28, 2017 at 11:10
  • Move the inArray (filterValue, filterChecked) from computed to methods instead Commented Jun 28, 2017 at 11:49
  • @VamsiKrishna "TypeError: Cannot read property 'length' of undefined" Commented Jun 28, 2017 at 12:02

1 Answer 1

2

I would code this like following:

  • Add a :checked binding that is applying the currently selected filter to your dropdown from your current activeFilters Vuex state
  • Use the current activeFilter value to toggle the state in your Vuex store on checkbox change - no need to check the current checkbox state from event. Direclty mutating the store from component is OK because there is no async process.
  • Create a component for the filterMenu that's managing the Vuex updating
  • Create a child component just for rendering the filter item

Please have a look at the demo below or this jsfiddle.

Note: Filtering in the demo is not perfect - just to have some filters to play with.

const filterItem = {
	props: ['item', 'changed'],
  computed: {
  	...Vuex.mapGetters(['activeFilters'])
  },
  template: `
  <li class="dropdown-child">
        <label >
            <input
                type="checkbox"
                :name="item.id"
                :value="item.name"
                :checked="isActive()"
                @change="emitChange"
                >
            <span>{{ item.name }}</span>

        </label>
    </li>
  `,
  methods: {
    isActive() {
    	return this.activeFilters.indexOf(this.item.name) != -1;
    },
  	emitChange() {
    	this.$emit('changed', {
      	item: this.item,
        checkState: !this.isActive() // toggle current checkState
      });
    }
  }
};

const filterMenu = {
  template: `
  	<div class="dropdown">
    <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Dropdown Example
      <span class="caret"></span></button>
    <ul class="dropdown-menu">
      <filter-item v-for="checkItem in filterOptions" :item="checkItem" @changed="changedFilter"
      :key="checkItem.id"></filter-item>
    </ul>
    </div>
  `,
  methods: {
    changedFilter(option) {
      this.$store.commit('updateFilters', option);
    }
  },
  data() {
    return {
      filterOptions: [{
        id: 0,
        name: 'all',
        checked: false
      }, {
        id: 1,
        name: 'numeric',
        checked: false
      }, {
        id: 2,
        name: 'letters',
        checked: false
      }]
    };
  },
  components: {
    filterItem: filterItem
  }
};


Vue.use(Vuex);

const store = new Vuex.Store({
  getters: {
    activeFilters: function(state) {
      return state.activeFilters;
    }
  },
  mutations: {
    updateFilters(state, filter) {
      console.log(filter);
      // filter.checkState = true --> check if in activeFilters list
      // filter.checkState = false --> remove filter from activeFilters
      let index = state.activeFilters.indexOf(filter.item.name);
      
      if ((index == -1) &&
      	filter.checkState) {
      	// item not in list && checked --> add to list
        state.activeFilters.push(filter.item.name);
      }
      else {
      	// item in list & toggled to false
        state.activeFilters.splice(index, 1); // remove from list
      }
    }
  },
  state: {
    activeFilters: ['all']
  }
});

new Vue({
  el: '#app',
  store: store,
  computed: {
  	...Vuex.mapGetters(['activeFilters'])
  },
  data: function() {
    return {
      list: [{
        id: 0,
        title: 'First Item'
      }, {
        id: 1,
        title: 'Second Item'
      }, {
        id: 2,
        title: 'Third Item'
      },  {
        id: 3,
        title: '1'
      },
       {
        id: 4,
        title: '2'
      },
       {
        id: 5,
        title: '3'
      },
       {
        id: 6,
        title: 'Test 1'
      },
      {
        id: 7,
        title: 'Test 2'
      }
      ]
    };
  },
  components: {
    filterMenu: filterMenu
  },
  methods: {
  	applyFilter(orgList) {
    	// activeFilters = all, numeric, letters
      let filtered = orgList;
      if (this.activeFilters.indexOf('all') == -1) {
      	// all not included
        let numericFiltered = [];
        let letterFiltered = [];
        
      	if (this.activeFilters.indexOf('numeric') > -1) {
        	numericFiltered = orgList.filter((item) => {
          	console.log('check match', item.title.match(/^\d+$/), item);
          	return /^[\d+\s+]+$/.test(item.title);
          });
        }
        
        if (this.activeFilters.indexOf('letters') > -1) {
        	letterFiltered = orgList.filter((item) => {
          	return /^[a-zA-Z\s+]+$/.test(item.title);
          });
        }
        filtered = numericFiltered.concat(letterFiltered);
      }
      
      console.log('new filter', filtered);
      return filtered;
    }
  }
});
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.3.1/vuex.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"></script>
<div id="app">

  <filter-menu></filter-menu>
  selected filters: {{$store.getters.activeFilters}}
  <h1>
    List to filter:
    </h1>
  <ul>
    <li v-for="listItem in applyFilter(list)" :key="listItem.id"> {{listItem.title}}</li>
  </ul>
</div>

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.