Laravel Livewire Multiple Selection with Virtual Select
Howdy!
Recently in one 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 , 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 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 :
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 :
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 :
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:
<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
...
@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 :
<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 :
<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.
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.
<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 :
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
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 or comment down below.
Thank you again and have a nice day.
Credits : Photo by Edu Grande on Unsplash