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

the_lar's avatar

Livewire component to select Client when certain Role is selected?

Hi there,

I have a simple admin page for creating a User which allows me to select the Role to give the User. I have 4 Roles, 2 of which are for Client specific stuff. When I create a User with either 'Client Adminstrator' or 'Client User' Roles, I need to ensure that they are also assigned to a Client.

I'm thinking that the best way to do this would be via a Livewire component that reacts to a change in the Role select field - if the selected Role is either Client Administrator or Client User, then the livewire component would load the Clients into a secondary select field.

I'm pretty new to Laravel and Livewire so roughly how would I achieve this, what are the basic steps to create this component and wire it up to the Role select field? Also, how would I go about ensuring that a value is selected in the livewire component but obviously make it so that it's not required when one of the other 2 Roles is selected?

Many thanks Kevin

0 likes
7 replies
tykus's avatar

Add a watcher to the component class which is watching for a change in the role property (using an updatedRole lifecycle hook).

When the selected role is one of the specific roles, you can change some piece of state to either show or enable a clients input field, and populate that field (if necessary).

Share your component class and template - and we can point you in the right direction

the_lar's avatar

Hi @tykus, thank you!

So I've ran php artisan make:livewire ShowClients

Then added my livewire component to my template:

...
<div class="mt-4">
  <x-jet-label for="role" value="{{ __('Role') }}" />
    <select id="role" class="border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm block mt-1 w-5/12" name="role" autofocus>
      <option value="">Empty</option>
      @forelse($roles as $role)
        <option value="{{ $role->name }}">{{ $role->name }}</option>
      @empty
        <option value="">No roles available</option>
      @endforelse
    </select>
  </div>
  @livewire('show-clients')
...

My component class ShowClients.php is pretty much empty:

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class ShowClients extends Component
{
    public function render()
    {
        return view('livewire.show-clients');
    }
}

As is my component template show-clients.blade.php:

<div>
    Show Clients here when either Client Administrator or Client User is selected above
</div>

So how would I wire it up so that I have a piece of state in my component class that listens and reacts to a change of the role dropdown?

tykus's avatar

@the_lar there is nothing to connect the role select field and the Livewire component. I meant that they should be part of the same component, so any change to role could be handled in the component

the_lar's avatar

@tykus Ah right... OK, I understand... I'll come back to this tomorrow now - thanks!

the_lar's avatar

@tykus ok got this working I think - my show-clients blade file now...

<div>
    <div class="mt-4">
        <x-jet-label for="role" value="{{ __('Role') }}" />
        <select id="role" wire:model="role_name" class="border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm block mt-1 w-5/12" name="role" autofocus>
            @forelse($roles as $role)
                <option value="{{ $role->name }}">{{ $role->name }}</option>
            @empty
                <option value="">No roles available</option>
            @endforelse
        </select>
    </div>
    @if(strpos($role_name, 'Client ')!==false)
        <div class="mt-4">
            <x-jet-label for="client" value="{{ __('Select Client') }}" />
            <select id="client" class="border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm block mt-1 w-5/12" name="role" autofocus>
                <option value="">Client list will be here eventually</option>
            </select>
        </div>
    @endif
</div>

And my component class ShowClients.php:

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Spatie\Permission\Models\Role;

class ShowClients extends Component
{
    public $role_name = null;

    public function render()
    {
        $roles = Role::where('name', '!=', 'Super Administrator')->get();
        return view('livewire.show-clients', ['roles' => $roles]);
    }
}

Any issues or ways I could improve this?

My other question is how do I make Client required - but only when Role is Client Administrator or Client User?

Currently my rules in my StoreUserRequest.php are:

public function rules()
    {
        $user = $this->route('user');
        return [
            'name' => 'required',
            'email' => 'required|email|unique:users,email,' . $this->email,
            'role' => 'required',
            'password' => [
                'required',
                'string',
                Password::min(8)
                    ->mixedCase()
                    ->numbers()
                    ->symbols()
                    ->uncompromised(),
                'confirmed'
            ],
        ];
    }

Thanks again for your help!

tykus's avatar
tykus
Best Answer
Level 104

@the_lar I would add a watcher that updates a piece of instance state e.g. public bool $showClients which is false by default:

public function updatedRoleName($value)
{
    $this->showClients = str($value)->startsWith('Client');
}

public function render()
{
    $roles = Role::where('name', '!=', 'Super Administrator')->get();
    $clients = $this->showClients ? Client::all() : [];

    return view('livewire.show-clients', compact('roles', 'clients'));
}
<select id="role" wire:model="role_name" class="/*brevity*/" name="role" autofocus>
    @forelse($roles as $role)
        <option value="{{ $role->name }}">{{ $role->name }}</option>
    @empty
        <option value="">No roles available</option>
    @endforelse
</select>
<!-- brevity -->
@if ($showClients)
    <div class="mt-4">
        <x-jet-label for="client" value="{{ __('Select Client') }}" />
        <select id="client" class="brevity" name="role" autofocus>
            @foreach($clients as $client)
                <option value="">Client list will be here eventually</option>
            @endforeach
        </select>
    </div>
@endif

For validation, you can use the required_if rule to check against the value of another input, e.g.

'client' => Rule::requiredIf(fn () => str($request->input('role))->startsWith('Client'),

Aside, you will probably be better advised to have the roles defined in a table and storing role_id rather that role_name on the users table.

the_lar's avatar

@tykus amazing - thank you for the help - will implement that tomorrow, I've got it working now both for creating and updating Users but sure this will improve it (very clever how it sorts out selecting the correct options when wired to a property).

Please or to participate in this conversation.