Back to Course |
Vue.js 3 + Laravel 11 + Vite: SPA CRUD

Category Dropdown: Second Composable

In this lesson, we will create a dropdown select to pick from a list of categories. For this, we will create a new composable and a new API endpoint with the API Resource.

categories select list


Let's start this lesson by creating a Controller with the API route.

php artisan make:controller Api/CategoryController
php artisan make:resource CategoryResource

app/Http/Controllers/Api/CategoryController.php:

use App\Http\Resources\CategoryResource;
 
class CategoryController extends Controller
{
public function index()
{
return CategoryResource::collection(Category::all());
}
}

routes/api.php:

use App\Http\Controllers\Api\CategoryController;
 
Route::get('posts', [PostController::class, 'index']);
Route::get('categories', [CategoryController::class, 'index']);

In the Resource, we will only add the id and name fields.

app/Http/Resources/CategoryResource.php:

class CategoryResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
];
}
}

Now that we have an API endpoint, we can create a new Composable and use it to get the categories. The composable for the categories is going to be almost identical to the one that we have for the posts.

resources/js/composables/categories.js:

import { ref } from 'vue'
 
export default function useCategories() {
const categories = ref({})
 
const getCategories = async () => {
axios.get('/api/categories')
.then(response => {
categories.value = response.data.data;
})
}
 
return { categories, getCategories }
}

Next, we need to add categories Composable to the PostsIndex Vue component and show all the categories in the select input above the table.

resources/js/components/Posts/Index.vue:

<template>
<div class="overflow-hidden overflow-x-auto p-6 bg-white border-gray-200">
<div class="min-w-full align-middle">
<div class="mb-4">
<select v-model="selectedCategory" class="block mt-1 w-full sm:w-1/4 rounded-md shadow-sm border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="" selected>-- Filter by category --</option>
<option v-for="category in categories" :value="category.id" :key="category.id">
{{ category.name }}
</option>
</select>
</div>
 
// ...
</div>
</div>
</template>
 
<script setup>
import { onMounted, ref } from "vue";
import { TailwindPagination } from 'laravel-vue-pagination';
import usePosts from "@/composables/posts";
import useCategories from "@/composables/categories";
 
const selectedCategory = ref('')
const { posts, getPosts } = usePosts()
const { categories, getCategories } = useCategories()
 
onMounted(() => {
getPosts()
getCategories()
})
</script>

After visiting the page you should see the select list.

categories select list