I have been working on filtering and sorting an array of objects in Vue. While I have successfully implemented the filtering functionality, I am now looking to incorporate a sorting feature as well. To achieve this, I have set up a dropdown component through which the selected sorting option is sent via the Event Bus to the component responsible for sorting.
However, my challenge lies in displaying both filter and sort options simultaneously.
Below is the component responsible for rendering the array of objects and handling the filtering/sorting:
<template>
<div class="cards">
<CountdownCard
v-for="(event, index) in filteredItems"
:key="index"
:event="event"
/>
</div>
</template>
<script>
import CountdownCard from '@/components/CountdownCard'
import EventBus from '@/components/EventBus'
export default {
components: {
CountdownCard
},
data() {
return {
events: [
{
title: 'Christmas',
date: 'December 25, 2020',
emoji: '🎅🏼',
type: 'holiday',
year: 2020,
month: 11,
day: 21,
hour: 0,
minute: 0
},
{
title: 'Spring',
date: 'March 21, 2020',
emoji: '💐',
type: 'season',
year: 2021,
month: 2,
day: 21,
hour: 0,
minute: 0
},
{
title: "Tyler's Birthday",
date: 'September 14, 2020',
emoji: '🎂',
type: 'custom',
year: 2020,
month: 8,
day: 14,
hour: 0,
minute: 0
}
filter: '',
sort: ''
}
},
mounted() {
return (
EventBus.$on('filter-categories', filter => {
this.filter = filter
}),
EventBus.$on('sort-categories', sort => {
this.sort = sort
})
)
},
computed: {
filteredItems: function() {
// filters at work
return (
this.events
// search filter
.filter(event => {
return event.title
.toLowerCase()
.includes(this.updateSearch.toLowerCase())
})
// category filters
.filter(event => {
if (this.filter == '' || this.filter == 'all') {
return this.events
} else {
return event.type == this.filter
}
})
)
},
sortedItems: function:{
// logic for sorting
}
}
</script>
And here is the component for the dropdown functionality:
<template>
<div class="dropDownContainer">
<div class="selection" :class="{ opened: opened }" @click="toggle">
<span class="selectionText">
{{ selected.label }}
<span class="downArrow"></span>
</span>
</div>
<transition name="grow">
<div class="options" v-if="opened">
<span
v-for="(option, index) in choices"
:key="index"
@click="makeSelection(option), emitSort(option.name)"
>
{{ option.label }}
</span>
</div>
</transition>
</div>
</template>
<script>
import EventBus from '@/components/EventBus'
export default {
props: {
choices: Array,
menuLabel: String
},
data: function() {
return {
selected: this.choices[0],
opened: false,
sortResult: ''
}
},
methods: {
toggle: function() {
this.opened = !this.opened
},
makeSelection: function(selected) {
this.selected = selected
this.opened = false
},
emitSort(option) {
this.sortResult = option
EventBus.$emit('sort-categories', this.sortResult)
}
}
}
</script>