Step 01: first we need to create Api/ClientController and ClientResource with artisan command
php artisan make:controller Api/ClientController php artisan make:resource ClientResource
Step 02: Changing ClientResource like below
class ClientResource extends JsonResource { /** * Transform the resource into an array. * * @return arraymixed> */ public function toArray(Request $request): array { return [ 'id' => $this->id, 'name' => $this->name, ]; } }
Step 03: Changing Api/ClientController like below
// at the top use App\Http\Resources\ClientResource; use App\Models\Client; class ClientController extends Controller { public function index() { return ClientResource::collection(Client::all()); } }
Step 04: Changing routes/api.php like below
Route::get('clients', [App\Http\Controllers\Api\ClientController::class, 'index']);
Step 05: After completing above steps for api end points lets head back to creating clients composable under resources/js/composables
import { ref } from 'vue' export default function useClients() { const clients = ref({}) const getClients = async () => { axios.get('/api/clients') .then(response => { clients.value = response.data.data; }) } return { clients, getClients } }
Step 06: After creating composable we need to import this inside components/Issues/Index.vue to populate clients dropdown above issues list table.
// first inside script tag adding following codes import { ref } from 'vue'; import useClients from "../../composables/clients"; const search_client = ref('') const { clients, getClients } = useClients() onMounted(() => { ... getClients() })
// then in component template adding following code like below <table> <tr> <th class="px-6 py-3 bg-gray-50 text-left"> </th> <th class="px-6 py-3 bg-gray-50 text-left"> <select v-model="search_client" :options="clients" placeholder="Filter By Client" :settings="{ 'width' : '100%' }"> <option value="" selected>-- Filter by client --</option> <option v-for="client in clients" :value="client.id" :key="client.id"> {{ client.name }} </option> </select> </th> <th> <th class="px-6 py-2 bg-gray-50 text-left"> </th> </th> <th> <th class="px-6 py-2 bg-gray-50 text-left"> </th> </th> <th></th> <th></th> </tr> </table> <table class="table"> <thead class="thead-dark"> .......Step 07: Now we can go on adding the feature of filtering list with client dropdown value.
// first need to add watch ( importing from vue ) for variable search_client import { ref, onMounted, watch } from 'vue'; ....... watch(search_client, (current, previous) => { getIssues(1, current) }) </script>
// next we need to tweak issues.js like below to take client_id to pass it to api end point const getIssues = async (page = 1, client = '') => { axios.get('/api/issues?page=' + page + '&client=' + client) .then(response => { issues.value = response.data; }) }
Step 08: After making changes
in composables and component we need to sync this change to
Api/IssuesController like below for client_id filtering using
conditional claue when
// at the top use Illuminate\Database\Eloquent\Builder; public function index() { $issues = Issue::with('client') ->when(request('client'), function (Builder $query) { $query->where('client_id', request('client')); }) ->paginate(3); return IssueResource::collection($issues); }
Step 09: Unfortunately, now client filtering would work with dropdown change but will break the pagination setup in such that if there are multiple pages for a particular client then paginate wont carry the client_id in the next pagination. We can add the following change to fix this inside Bootstrap4Pagination component inside Index.vue template
// this change will pass necessary parameters in composable which will then be passed to api endpoints for fetching correct rows for particular filtered paramters <Bootstrap4Pagination :data="issues" @pagination-change-page="page => getIssues(page, search_client)" />