Laravel Livewire Multiple Selection with Virtual Select
Tags: laravel, livewire, javascript, php
Published: 2023-06-27 00:40:40

Hello.
Recently in of our projects, we had to create a multiple selection dropdown. We were using Livewire, and vanilla JavaScript (no AlpineJS), so the options were either using the default multiple select, which is to be honest, ugly.
So we have to check for something else. The next options was Select2 Js, a popular jQuery library.
The problem with Select2 was the jQuery, we have to import jQuery just for that, and also the design wasn't that good actually.
 
So after little research, and so many thanks for [skywalker](https://forum.laravel-livewire.com/u/skywalker) , we were introduced to Virtual Select. 

What we like about Virtual Select is the looks and the performance of it. It was amazing really, no dependencies and it worked from the first try.
Unfortunately, the plugin doesn't support ES6 yet. 
But if you want to contribute, here is [the link](https://github.com/sa-si-dev/virtual-select/issues/168) to issue discussing the matter.

In this tutorial we will cover how to import Virtual Select, and how to retrieve data in our component.
 > **_NOTE:_** : This tutorial will assume you have a Laravel installation in place already and Livewire is also installed.

 > **_NOTE:_** : In this tutorial we will not cover how to get data from API, it maybe for another tutorial soon 🤞.

That being said, the first thing to do is to create the Livewire component. A common use case for this would be as follows: 
Select multiple permissions for a specific user. 
So our component would be named, for example `EditUser`.
So run this in your terminal : 
```bash
php artisan livewire:make EditUser 
```
After creating the component, the next thing to do is open the class, called `EditUser.php`, and edit the `render` method as follows : 

```php
use App\Models\Permission;
use Livewire\Component;

class EditUser extends Component
{
    public function render()
    {
        $permissions = Permission::query()->get();
        return view('livewire.edit-user')->with('permissions', $permissions);
    }
}
```

As you can see, we added the list of permissions needed to assign them to the desired user.
Another thing to do here, is to prepare a public property to hold those assigned permissions. So the class will be as follows : 

```php
use App\Models\Permission;
use Livewire\Component;

class EditUser extends Component
{

    public $selectedPermissions= [];


    public function render()
    {
        $permissions = Permission::query()->get();
        return view('livewire.edit-user')->with('permissions', $permissions);
    }
}
```
And of course your component would hold other properties such as the user property and other stuff, but for the sake of this tutorial, we are making it simple. 

Anyways, moving on now to the frontend. The first thing you need to do is to "import" Virtual Select CSS & JS assets. 
You can download them, or use a CDN. 
For this example, we will use jsdelivr.com .
So the first thing you need, is to use them in your main layout file as follows: 

```html
    <script src="https://cdn.jsdelivr.net/npm/virtual-select-plugin@1.0.39/dist/virtual-select.min.js" integrity="sha256-Gsn2XyJGdUeHy0r4gaP1mJy1JkLiIWY6g6hJhV5UrIw=" crossorigin="anonymous"></script>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/virtual-select-plugin@1.0.39/dist/virtual-select.min.css" integrity="sha256-KqTuc/vUgQsb5EMyyxWf62qYinMUXDpWELyNx+cCUr0=" crossorigin="anonymous">
```
Also, you may want to use `@stack` for the JavaScript we will use in the component later.
After those modifications, our main layout file would be look like this 
```html
...
    @livewireStyles
    <script src="https://cdn.jsdelivr.net/npm/virtual-select-plugin@1.0.39/dist/virtual-select.min.js" integrity="sha256-Gsn2XyJGdUeHy0r4gaP1mJy1JkLiIWY6g6hJhV5UrIw=" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/virtual-select-plugin@1.0.39/dist/virtual-select.min.css" integrity="sha256-KqTuc/vUgQsb5EMyyxWf62qYinMUXDpWELyNx+cCUr0=" crossorigin="anonymous">
</head>

<body>




    @livewireScripts
    @stack('js')
    ...
</body>
...
```
Now moving on to our component. 
The first thing to do is to initiate an empty `div` for the plugin to work. So open `edit-user.blade.php` and add the empty div with an `id` so we can reference it later. 
At first, our component will look like this : 
```html
<div>
    <div id="permissions"></div>
</div>
```

After initializing the DOM element, the next thing to do is to initiate the plugin. In order to do so, we will "push" the stacked `js` we defined earlier. It will look like this : 
```html
<div>
    <div id="permissions"></div>
    @push('js')
        <script>
            
        </script>
    @endpush
</div>
```

And now let's get to work. We need to define our options, to do so, we can create a new JavaScript variable to hold the permissions coming from the database. 

```blade
            const permissions = [
                @foreach ($permissions as $permission)
                    {
                        label: "{{ $permission->name }}",
                        value: "{{ $permission->id }}"
                    },
                @endforeach
            ];

```
This piece of code, will be able to transform the collection of permissions into a JavaScript array. 
After that, what we need to do is to initiate the plugin itself. 
```html
<div>
    <div id="permissions"></div>
    @push('js')
        <script>
            const permissions = [
                @foreach ($permissions as $permission)
                    {
                        label: "{{ $permission->name }}",
                        value: "{{ $permission->id }}"
                    },
                @endforeach
            ];
            VirtualSelect.init({
                ele: '#permissions',
                multiple: true,
                options: permissions,
            });
        </script>
    @endpush
</div>
```
As you can see, we called the `init` method with the options :
<li>
`ele` : The element of the DOM that will render the dropdown
</li>
<li>
`multiple` : whether to indicate it's a multiple selection or not
</li>
<li>
`options` : the data the dropdown will populated with, which we defined earlier.
</li>

At this moment, if we visit the page, our component will be like this: 
{% embed https://vimeo.com/839911117?share=copy %}

At this stage, everything is working perfectly, but the problem is how to tell Livewire about those selections. At this point, we will use Livewire beauty ❤️

In order to pass the data to Livewire, we will use the JavaScript event listener, whenever the selection is changed, we will send them to our component. 
So in our view file, what we need to add is the following code 

```js
            let selectedPermissions = document.querySelector('#permissions');
            selectedPermissions.addEventListener('change', () => {
                let data = selectedPermissions.value;
                @this.set('selectedPermissions', data);
            });

```
What we did is we first get the DOM element defined earlier, then we attach to it an event listener, whenever the selection changes, we want to get the selection and send it to our component.
And then at the component level, the selected data will be available at `$selectedPermissions` property, so you can assign them to the user. 

I hope you liked this tutorial, and you gain information about it.
If something is not clear or you want ask about further information, you can contact me on [Twitter](https://twitter.com/Koossaayy) or comment down below.
Thank you again and have a nice day.

[Original Post](https://koossaayy.tn/laravel-livewire-multiple-selection-with-virtual-select-)
Credits : Photo by <a href="https://unsplash.com/@edgr?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Edu Grande</a> on <a href="https://unsplash.com/photos/0vY082Un2pk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>