Transitioning from Laravel Livewire to Laravel Vue has presented a challenge in recreating the necessary sorting logic in Vue. I've managed to implement basic table sorting by clicking on the table headers. However, I now need help with achieving a feature where clicking on a column header after it has been sorted in descending order ('desc') will revert it back to its original unsorted state, similar to the behavior in the Livewire Component example below. Any assistance in implementing this functionality in Vue would be greatly appreciated.
User Index Vue Component - Current Behavior
https://i.sstatic.net/o5gD7.gif
User Index Livewire Component - Required Behavior
https://i.sstatic.net/mMKUv.gif
User Index Vue Component - Script
<script>
export default {
props : ['users'],
data() {
return {
sortField: '',
sortDirection: 'asc'
}
},
methods: {
sortBy: function(column) {
if (column === this.sortField) {
this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
} else this.sortDirection = 'asc';
this.sortField = column;
}
},
computed:{
sortedUsers: function() {
return this.users.sort((a, b) => {
let modifier = 1;
if (this.sortDirection === 'desc') modifier = -1;
if (a[this.sortField] < b[this.sortField]) return -1 * modifier;
if (a[this.sortField] > b[this.sortField]) return 1 * modifier;
return 0;
});
}
}
}
</script>
User Index Vue Component - Template
<template #head>
<data-table-heading sortable :direction="sortField === 'id' ? sortDirection : null" @click="sortBy('id')" class="pr-0">ID</data-table-heading>
<data-table-heading sortable :direction="sortField === 'name' ? sortDirection : null" @click="sortBy('name')">Name</data-table-heading>
<data-table-heading sortable :direction="sortField === 'email' ? sortDirection : null" @click="sortBy('email')" class="w-screen">Email</data-table-heading>
<data-table-heading sortable :direction="sortField === 'role' ? sortDirection : null" @click="sortBy('role')">Role</data-table-heading>
<data-table-heading sortable :direction="sortField === 'created_at' ? sortDirection : null" @click="sortBy('created_at')">Date</data-table-heading>
</template>
Data Table Heading Vue Component - Template
<span class="relative flex items-center">
<div v-if="direction === 'asc'">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</div>
<div v-else-if="direction === 'desc'">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"></path>
</svg>
</div>
<div v-else>
<svg class="w-3 h-3 opacity-0 group-hover:opacity-100 transition-opacity duration-300" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"></path>
</svg>
</div>
</span>
Edit
Livewire Component Sorting
public $sorts = [];
public function sortBy($field)
{
if (! isset($this->sorts[$field])) return $this->sorts[$field] = 'asc';
if ($this->sorts[$field] === 'asc') return $this->sorts[$field] = 'desc';
unset($this->sorts[$field]);
}