Monday, February 26, 2024
 Popular · Latest · Hot · Upcoming
137
rated 0 times [  140] [ 3]  / answers: 1 / hits: 19631  / 7 Years ago, tue, march 7, 2017, 12:00:00

I've moved on a little in my Vue development to looking at using Vuex for state.



Previously, I had one master Vue component that had search, an array of items to loop over and the item iteration itself.



As I looked to split out the single component into several components (search, list of items and an item) - I saw that I couldn't change reactive properties from within a child component.



So, how should I be filtering my list of items. Do I handle that by way of state mutation or by computed properties in the child component?



Previously I was doing



export default {
components: { Job },
data() {
return {
list: [],
categories: [],
states: states,
countries: countries,
keyword: '',
category: '',
type: '',
state: '',
country: '',
loading: true
}
},
mounted() {
axios.get('/api/cats.json')
.then(response =>
this.categories = response.data.data
)
axios.get('/api/jobs.json')
.then(function (response) {
this.list = response.data.data;
this.loading = false;
}.bind(this))
},
computed: {
filteredByAll() {
return getByCountry(getByState(getByType(getByCategory(getByKeyword(this.list, this.keyword), this.category), this.type), this.state), this.country)
},
filteredByKeyword() {
return getByKeyword(this.list, this.keyword)
},
filteredByCategory() {
return getByCategory(this.list, this.category)
},
filteredByType() {
return getByType(this.list, this.type)
},
filteredByState() {
return getByState(this.list, this.state)
},
filteredByCountry() {
return getByCountry(this.list, this.country)
}
}
}

function getByKeyword(list, keyword) {
const search = keyword.trim().toLowerCase()
if (!search.length) return list
return list.filter(item => item.name.toLowerCase().indexOf(search) > -1)
}

function getByCategory(list, category) {
if (!category) return list
return list.filter(item => item.category == category)
}

function getByType(list, type) {
if (!type) return list
return list.filter(item => item.type == type)
}

function getByState(list, state) {
if(!state) return list
return list.filter(item => item.stateCode == state)
}

function getByCountry(list, country) {
if(!country) return list
return list.filter(item => item.countryCode == country)
}


Should my filters apply from within the search component or as a mutation within state?


More From » filtering

 Answers
9

Should my filters apply from within the search component or as a mutation within state?




I am not sure as to why you want to mutate your state for filtering, what if some other filter had to be applied? I suggest using as many getters as you have filters in your components' computed.



Methods can be placed in a js file, so that you can re-use them elsewhere.



export function getByKeyword(list, keyword) {
const search = keyword.trim().toLowerCase()
if (!search.length) return list
return list.filter(item => item.name.toLowerCase().indexOf(search) > -1)
}

export function getByCategory(list, category) {
if (!category) return list
return list.filter(item => item.category == category)
}

export function getByType(list, type) {
if (!type) return list
return list.filter(item => item.type == type)
}

export function getByState(list, state) {
if(!state) return list
return list.filter(item => item.stateCode == state)
}

export function getByCountry(list, country) {
if(!country) return list
return list.filter(item => item.countryCode == country)
}


You can have this in your store:



// someStoreModule.js

import {getByKeyword, getByCategory, getByType, getByState, getByCountry} from 'path/to/these/functions/file.js'

state: {
list: [],
categories: [],
states: states,
countries: countries,
keyword: '',
category: '',
type: '',
state: '',
country: '',
loading: true
},
getters: {
filteredByAll() {
return getByCountry(getByState(getByType(getByCategory(getByKeyword(state.list, state.keyword), state.category), state.type), state.state), state.country)
},
filteredByKeyword() {
return getByKeyword(state.list, state.keyword)
},
filteredByCategory() {
return getByCategory(state.list, state.category)
},
filteredByType() {
return getByType(state.list, state.type)
},
filteredByState() {
return getByState(state.list, state.state)
},
filteredByCountry() {
return getByCountry(state.list, state.country)
}
}


Lastly, your component can use it like so:



import { mapGetters } from 'vuex'

export default {
...
computed: {
...mapGetters([ // you won't need to destructure if
'filteredByKeyword', // you have no plans of adding other computed
'filteredByCategory', // properties. It would be safer anyway to keep it.
'filteredByAll',
'filteredByType',
'filteredByState',
'filteredByCountry'
])
}
...
}

[#58638] Monday, March 6, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
samara

Total Points: 326
Total Questions: 106
Total Answers: 103

Location: Cook Islands
Member since Thu, May 21, 2020
4 Years ago
;