Step 01: Adding visual changes for table headers inside Index.vue inside template tag like below
<thead class="thead-dark"> <tr> <th> <div style="cursor: pointer;" class="" @click="updateOrdering('id')"> <span :class="{ 'font-bold text-info': order_column === 'id' }"> ID </span> <span :class="{ 'text-info': order_direction === 'asc' && order_column === 'id', 'd-none': order_direction !== '' && order_direction !== 'asc' && order_column === 'id', }">↑</span> <span :class="{ 'text-info': order_direction === 'desc' && order_column === 'id', 'd-none': order_direction !== '' && order_direction !== 'desc' && order_column === 'id', }">↓</span> </div> </th> <th>Client</th> <th> <div style="cursor: pointer;" class="" @click="updateOrdering('title')"> <span :class="{ 'font-bold text-info': order_column === 'title' }"> Issue </span> <span :class="{ 'text-info': order_direction === 'asc' && order_column === 'title', 'd-none': order_direction !== '' && order_direction !== 'asc' && order_column === 'title', }">↑</span> <span :class="{ 'text-info': order_direction === 'desc' && order_column === 'title', 'd-none': order_direction !== '' && order_direction !== 'desc' && order_column === 'title', }">↓</span> </div> </th> <th style="width: 40%;">Description</th> <th> <div style="cursor: pointer;" class="" @click="updateOrdering('created_at')"> <span :class="{ 'font-bold text-info': order_column === 'created_at' }"> Created </span> <span :class="{ 'text-info': order_direction === 'asc' && order_column === 'created_at', 'd-none': order_direction !== '' && order_direction !== 'asc' && order_column === 'created_at', }">↑</span> <span :class="{ 'text-info': order_direction === 'desc' && order_column === 'created_at', 'd-none': order_direction !== '' && order_direction !== 'desc' && order_column === 'created_at', }">↓</span> </div> </th> </tr> </thead>
three changes to note here as we have added one method updateOrdering and two variables order_column and order_direction which are used to check which column header is being clicked and uparrow and downarrow are being changed accordingly to represent ascending and descending rows.
Step 02: now adding below changes inside script tag for component
const order_column = ref('created_at') const order_direction = ref('desc') const updateOrdering = (column) => { order_column.value = column; order_direction.value = (order_direction.value === 'asc') ? 'desc' : 'asc'; getIssues(1, search_client.value, order_column.value, order_direction.value ); }
Step 03: Adding following changes inside issues.js composable for passing order_column and order_direction value to api end point
const getIssues = async (page = 1, client = '', order_column = 'created_at', order_direction = 'desc' ) => { axios.get('/api/issues?page=' + page + '&client=' + client + '&order_column=' + order_column + '&order_direction=' + order_direction ) .then(response => { issues.value = response.data; }) }
Step 04: Changing index() method of Api/IssuesController like below to sync the changes of client_id filtering for order_column and order_direction parameters with validation
public function index() { $order_column = request('order_column', 'created_at'); if (! in_array($order_column, ['id', 'title', 'created_at'])) { $order_column = 'created_at'; } $order_direction = request('order_direction', 'desc'); if (! in_array($order_direction, ['asc', 'desc'])) { $order_direction = 'desc'; } $issues = Issue::with('client') ->when(request('client'), function (Builder $query) { $query->where('client_id', request('client')); }) ->orderBy($order_column, $order_direction) ->paginate(10); return IssueResource::collection($issues); }