Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

lukeboy_2002's avatar

Select2 question

I followed a tutorial online to implement select2 on my roles to add the permissions. It works but I want to see the badges in the select options and olso want to delete them there. I have the following code that works.

livewire: RolesForm

<?php
namespace App\Http\Livewire\Admin\Roles;

use App\Models\Permission;
use App\Models\Role;
use Illuminate\Contracts\View\View;
use Illuminate\Validation\Rule;
use Livewire\Component;

class RolesForm extends Component
{
    public Role $role;
    public bool $editing = false;
    public array $permissions = [];
    public array $listsForFields = [];

    public function mount(Role $role): void
    {
        $this->role = $role;

        $this->initListsForFields();

        if ($this->role->exists) {
            $this->editing = true;

            $this->permissions = $this->role->permissions()->pluck('id')->toArray();
        }
    }

    public function render(): View
    {
        return view('livewire.admin.roles.roles-form');
    }

    public function submit()
    {
        $this->validate();

        $this->role->save();

        $this->role->permissions()->sync($this->permissions);

        return redirect()->route('admin.roles.index');
    }

    protected function rules(): array
    {
        return [
            'role.name' => [
                'string',
                Rule::unique('roles', 'name')->ignore($this->role),
                'required',
                'permissions' => ['required', 'array']
            ],
        ];
    }

    protected function initListsForFields(): void
    {
        $this->listsForFields['permissions'] = Permission::pluck('name', 'id')->toArray();
    }
}

Livewire template roles-form

<div>
    <x-main.loading />

    <div class="overflow-x-auto relative shadow-md sm:rounded-lg px-4 py-2">
        <div class="flex justify-between items-center space-x-4 pb-4 max-w-7xl">
            <div class="flex items-center">
                <div class="border-l-4 border-orange-500 pl-4 flex justify-between items-center">
                    <x-links.header href="#">{{ $editing ? 'Edit ' . $role->name : 'Create Role' }}</x-links.header>
                </div>
            </div>
        </div>

        <div class="relative overflow-x-auto shadow-md sm:rounded-lg">
            <x-cards.default class="p-8">
                <form wire:submit.prevent="submit" class="pt-3">
                    @csrf
                    <div>
                        <x-jet-label for="name" value="Name" />
                        <x-jet-input wire:model.defer="role.name" type="text" name="name" id="name" :value="old('name')" required autofocus />
                        <x-jet-input-error for="role.name" class="mt-2" />
                    </div>

                    <div class="mt-4">
                        <x-jet-label for="permissions" value="Permissions" />
                        <x-select2 class="mt-1" id="permissions" name="permissions" :options="$this->listsForFields['permissions']" wire:model="permissions" multiple />
                        <x-jet-input-error for="permissions" class="mt-2" />
                    </div>

                    <div class="flex justify-end items-center space-x-2 mt-5">
                        <x-buttons.default class="rounded-lg" type="submit">
                            save
                        </x-buttons.default>
                        <x-links.btn-secundary href="{{ route('admin.roles.index') }}" class="rounded-lg">
                            cancel
                        </x-links.btn-secundary>
                    </div>
                </form>
            </x-cards.default>
        </div>
    </div>
</div>

Component select2

<?php

namespace App\View\Components;

use Illuminate\View\Component;
use Illuminate\Contracts\View\View;

class Select2 extends Component
{
    public function __construct(public mixed $options)
    {
        //
    }

    public function render(): View
    {
        return view('components.select2');
    }
}

Component select2

<div>
    <div wire:ignore class="w-full">
        <select class="select2" data-placeholder="{{ __('Select your option') }}" {{ $attributes }}>
            @if(!isset($attributes['multiple']))
                <option selected="selected"></option>
            @endif
            @foreach($options as $key => $value)
                <option value="{{ $key }}">{{ $value }}</option>
            @endforeach
        </select>
    </div>

    @push('scripts')
        <script>
            document.addEventListener("livewire:load", () => {
                let el = $('#{{ $attributes['id'] }}')
                function initSelect() {
                    el.select2({
                        placeholder: '{{ __('Select your option') }}',
                        allowClear: !el.attr('required'),
                    })
                }
                initSelect()
                Livewire.hook('message.processed', (message, component) => {
                    initSelect()
                });
                el.on('change', function (e) {
                    let data = $(this).select2("val")
                    if (data === "") {
                        data = null
                    }
                @this.set('{{ $attributes['wire:model'] }}', data)
                });
            });
        </script>
    @endpush
</div>

Now when I save the permissions are saved and I can deselect them.

but when I change Component select2 with adding the class js-example-theme-multiple and add a script like o the site of select2. But now there there a now changes saved

<div>
    <div wire:ignore class="w-full">
        <select class="select2 js-example-theme-multiple" data-placeholder="{{ __('Select your option') }}" {{ $attributes }}>
            @if(!isset($attributes['multiple']))
                <option selected="selected"></option>
            @endif
            @foreach($options as $key => $value)
                <option value="{{ $key }}">{{ $value }}</option>
            @endforeach
        </select>
    </div>

    @push('scripts')
        <script>
            document.addEventListener("livewire:load", () => {
                let el = $('#{{ $attributes['id'] }}')
                function initSelect() {
                    el.select2({
                        placeholder: '{{ __('Select your option') }}',
                        allowClear: !el.attr('required'),
                    })
                }
                initSelect()
                Livewire.hook('message.processed', (message, component) => {
                    initSelect()
                });
                el.on('change', function (e) {
                    let data = $(this).select2("val")
                    if (data === "") {
                        data = null
                    }
                @this.set('{{ $attributes['wire:model'] }}', data)
                });
            });

             $(".js-example-theme-multiple").select2({
                 theme: "classic"
            });
        </script>
    @endpush
</div>
0 likes
0 replies

Please or to participate in this conversation.