Create Dynamic Drop-down component with Vue 3, Tailwind CSS and Laravel 9

Mostafa Said - Feb 9 '22 - - Dev Community

Good day everyone 👋

In this article i'm going to explain how to build a fully dynamic drop-down VueJS 3 component with HTML, Tailwind CSS 3 and Laravel 9. We will use composition API which was introduced in the latest version of Vue, our drop-down's content will be looping over Mysql database so it's a dynamic component and also we will introduce Vue3 click-outside npm package to close the drop-down when the user clicks anywhere else on the screen.

By the end of this 2 parts series you will be able to build this:

Table of Content:

By the end of this tutorial, you should know the below by heart ❤️:

  • How to install Node and npm.
  • How to create new Laravel 9 project.
  • How to create and connect to a database.
  • How to seed fake users to database.
  • How to install tailwind CSS.
  • How to install Vue, Vue Router and Vue Loader and activate them.
  • How to prepare your blade file to receive your component via Vue-router
  • How to make a dynamic drop-down vue js 3 component using composition API and click-outside package and style it with Tailwind CSS 3.
  • How to receive Json data from database via route and loop over them with axios in Vue component.

A piece of advice before starting, this is a step by step guide so it's better if you code along as we will be using multiple frameworks and techniques. Let's get to it? 👇

0- I'm using

1- npm & Node
2- Laravel 9 🥳
3- Table plus
4- Tailwind CSS 3
5- Vue JS 3 (With Vue Router & Vue Loader)
6- Windows Terminal
7- VS Code

1- Install Nodejs and npm:

  • First thing you need to make sure that you have Node and npm installed on your machine.
  • You can check that by opening up the terminal and type those two commands:

npm -v
node -v



PS C:\Users\Moose> node -v
v16.13.2
PS C:\Users\Moose> npm -v
8.4.0


Enter fullscreen mode Exit fullscreen mode

2- Start your Laravel Project:

  • If you already have a project, you can skip this step 👇.
  • I use composer to create Laravel projects.
  • You can download composer from here: https://getcomposer.org/
  • Open up your terminal and create your Laravel project in the desired directory.
  • The below command will create new Laravel 9 project for us.


PS C:\Users\Moose> cd F:\Projects
PS F:\Projects> composer create-project laravel/laravel dropdown-component


Enter fullscreen mode Exit fullscreen mode

3- Install Database Management Tool:

  • I use free version of table plus to manage my databases.
  • You can download it from here: https://tableplus.com/
  • This really doesn't require any instructions, keep clicking next and leave everything to default settings.
  • You don't have to use it if you prefer another database management tool.

4- Create a Database:

  • I will use MySQL Database. You're free to use whatever database you like.
  • There are many ways to create Mysql Database, to know more you can visit this link.
  • I will create a database using MySQL Command Line Client and name it 'dropdown'.

mysql> create database dropdown;

5- Connect to Database:

  • Open your Laravel project in the preferred code editor, in my case I will use VS Code.
  • Head to your env file in the main Laravel project directory.
  • In the below section make sure to update all the info to match your created database.

env file screenshot

  • Open table plus -> click on 'Create new connection' -> MySQL.
  • Fill in the fields with the info you just created.
  • You can name the connection with anything you want.
  • After filling the fields click test then connect.

Table plus connect layout

6- Create fake users & Migrate with seed:

  • Head to database\seeders\DatabaseSeeder.php and remove the comment from the line in run() function.
  • This will allow you to create 10 fake users with Laravel Factory.

Seeders php file

  • Open up the terminal in the main project directory to run your migration command and --seed the fake users to database.

PS F:\Projects\dropdown-component> php artisan migrate --seed

  • You can test that everything is as expected to this point, head to resources\views\welcome.blade.php and clear it,
  • Create new HTML boilerplate and in the body write the below code.


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>dropdown</title>
</head>
<body>
    @foreach ($users as $user)
        <p>The name of the user is: {{ $user->name }}</p>
    @endforeach
</body>
</html>


Enter fullscreen mode Exit fullscreen mode
  • Open the terminal and hit the below code within the project main directory to serve and see your project in browser.

PS F:\Projects\dropdown-component> php artisan serve

  • You should see now that Laravel is looping over the database User's table and giving us back the name for each user.

7- Install Tailwind CSS:

  • If you would like to install Tailwind CLI you can visit my article for a step by step guide on how to do that 🔗 CLICK HERE
  • Or you can simply add the following line of code to import tailwind CDN in your project by following the steps in the documentation HERE
  • In my case, I will use tailwind CLI for better results.

8- Install Vue and it's dependencies:

  • Open the terminal in your project's main directory and run the below code to install Vue, Vue Router and Vue Loader.

PS F:\Projects\dropdown-component> npm install vue@next vue-router@next vue-loader@next

  • I also prefer running npm run watch and leave it running in the backgroud while I'm working on my project.

PS F:\Projects\dropdown-component> npm run watch

  • Head to webpack.mix.js file in your project's main directory and .vue() right before postCss.


mix.js("resources/js/app.js", "public/js")
    .vue()
    .postCss("resources/css/app.css", "public/css", [require("tailwindcss")]);


Enter fullscreen mode Exit fullscreen mode

9- Prepare your blade file:

  • Head to the welcome.blade.php file and clear the body then I will add empty divs that will contain our Vue component with router-vue.
  • Don't forget to add id="app".


<body>
    <main class="max-w-6xl mx-auto mt-6 lg:mt-20 space-y-6" 
                 id="app">

        <div class="max-w-xl mx-auto mt-10 text-center">
            <div class="space-y-2 lg:space-y-0 lg:space-x-4 mt-8" 
                        id="app">
                <div class="relative lg:inline-flex items-center 
                            bg-blue-100 rounded-xl">

                    <router-view />

                </div>
            </div>
        </div>

    </main>
</body>


Enter fullscreen mode Exit fullscreen mode

10- Enable Vue and make component:

  • Head to resources\js\app.js and add the below code and save to enable Vue JS.


import { createApp } from "vue";

createApp({
    components: {},
}).mount("#app");


Enter fullscreen mode Exit fullscreen mode
  • Head to resources\js and create a subfolder called components and within that folder create DropdownComponent.vue file.
  • Inside the file write Vue default setup and leave a 'hello world' for testing.


<template>
    <h1 class="text-red-500 text-bold">Hello world</h1>
</template>

<script>
export default {};
</script>

<style></style>


Enter fullscreen mode Exit fullscreen mode
  • Now it's time to create our route to this component.
  • Head to resources\js and create a subfolder called router and inside it create index.js file.
  • Write the below code inside index.js file.
  • In this code you're basically telling your project

Hi, I want to use Vue router and import this component whenever I'm in that path



import { createRouter, createWebHistory } from "vue-router";
import DropdownComponent from "../components/DropdownComponent";

const routes = [
    {
        path: "/",
        name: "home",
        component: DropdownComponent,
    },
];

export default createRouter({
    history: createWebHistory(),
    routes,
});


Enter fullscreen mode Exit fullscreen mode
  • Head back to resources\js\app.js and import your router and component.
  • End result below.


import { createApp } from "vue";
import router from "./router";
import DropdownComponent from "./components/DropdownComponent";

createApp({
    components: {
        DropdownComponent,
    },
})
    .use(router)
    .mount("#app");


Enter fullscreen mode Exit fullscreen mode
  • Open up the terminal and stop your npm run watch if it's running and run it again to compile your files properly.
  • Now if you refresh you broswer you should see your hello world.

11- Build the Drop-down:

  • Head back to DropdownComponent.vue and within the template you can start building your Dropdown.
  • I create a container div which contains a button and a div. I want when I press on the button I can see list of links.
  • I will add a @click to the button and conditionally show the div with links if some condition is true.


<template>
    <div>
        <button
            @click="showUsers"
            class="flex max-h-52 w-full overflow-auto py-2 pl-3 pr-9 text-sm font-semibold lg:inline-flex lg:w-32"
        >
            Users
        </button>
        <div
            v-show="usersToggle"
            class="mt-1 w-full rounded-xl bg-blue-100 py-2"
        >
            <a href="#" class="block mt-1 w-full rounded-xl bg- 
                               blue-100 py-2">
                Testing
            </a>
        </div>
    </div>
</template>


Enter fullscreen mode Exit fullscreen mode
  • Now let's move to the script tags to import what we need and write down our logic using composition API.
  • I will import ref and onMounted then create a usersToggle and set it to false and make the click on the button change it to true.


<script>
import { ref, onMounted } from "vue";
export default {
    name: "home",
    setup() {
        const usersToggle = ref(false);

        const showUsers = () => {
            usersToggle.value = !usersToggle.value;
        };

        return { showUsers, usersToggle };
    },
};
</script>


Enter fullscreen mode Exit fullscreen mode
  • Now if you check your browser, whenever you click on the button it will open a drop-down list with the testing links and if you click it again it will close.

12- Vue JS 3 click outside:

  • Head to the following LINKand install npm click outside package for Vue3. PS F:\Projects\dropdown-component> npm install --save click-outside-vue3
  • Head to app.js and import it import vClickOutside from "click-outside-vue3"; and don't forget to add vClickOutside just next to use router .use(router, vClickOutside)
  • Head to DropdownComponent.vue and import it within the script tags import vClickOutside from 'click-outside-vue3'
  • Add the directive as is says in the DOCs


    directives: {
        clickOutside: vClickOutside.directive,
    },


Enter fullscreen mode Exit fullscreen mode
  • Then in the setup make sure to create your function that will make the usersToggle false again by clicking outside and return it.


setup() {
        const usersToggle = ref(false);

        const showUsers = () => {
            usersToggle.value = !usersToggle.value;
        };

        const onClickOutside = (event) => {
            usersToggle.value = false;
        };

        return { showUsers, usersToggle, onClickOutside };
    },


Enter fullscreen mode Exit fullscreen mode
  • Within the template, add v-click-outside="onClickOutside" to the container div.
  • Now if you test it on browser it works like a charm.

13- Loop over users in Database:

  • Create a new route to receive your Json data from database.


Route::get('list', function () {
    return response()->json([
        'users' => \App\Models\User::all()
    ], Response::HTTP_OK);
});


Enter fullscreen mode Exit fullscreen mode
  • Head back to your component and adjust the anchor tag to loop over users array.


            <a
                href="#"
                class="block mt-1 w-full rounded-xl bg-blue-100 
                       py-2"
                v-for="user in users"
                :key="user.id"
            >
                {{ user.name }}
            </a>


Enter fullscreen mode Exit fullscreen mode
  • In the setup, create empty array for users.


        const users = ref([]);


Enter fullscreen mode Exit fullscreen mode
  • Then write the below code to say:

Hey! Get my Json data as a response from this path, and change the users array value to whatever data in the response.
Not only this, I want this data as soon as my component is mounted and return it to me.



        const getUsers = () => {
            axios.get("/list").then((response) => {
                users.value = response.data.users;
            });
        };

        onMounted(() => {
            getUsers();
        });

        return {
            showUsers,
            usersToggle,
            onClickOutside,
            getUsers,
            users,
        };


Enter fullscreen mode Exit fullscreen mode
  • Now, If you check your browser you will see your users names in a dynamic functional dropdown menu.

This is a final screen for my code in case you want to compare it to yours:
Vue dropdown component

Also you can find full code on Github: https://github.com/MooseSaeed/dropdown-component

14- Finishing:

Congratulations you've created a complex Vue component with the latest release of everything 🎉🥳

Thank you so much for reading my article and I hope it was helpful for everyone.

If you have any questions, comments or feedback please leave them below or find me on Twitter and DMs are open.

. . . . . . . . . . . . . . . . . . . . . . . . .