Black Friday: coupon FRIDAY24 for 40% off Yearly/Lifetime membership! Read more here

Select Unique Options per Resource

2024-05-17

Sometimes, we have to limit the number of entries we can select. For example, your Employee can only work on one Client at a time.

When dealing with Select fields, we typically pass in a list of options to the options property like this:

Forms\Components\Select::make('employee_id')
->label('Assigned Employee')
->options(User::pluck('name', 'id'))

And this works perfectly fine. However, sometimes, we need to disable specific options in the list. For example, if the Option has already been selected, we might want to hide it. To do this, we can write a custom Closure that does that:

Forms\Components\Select::make('employee_id')
->label('Assigned Employee')
->options(function ($record) {
return User::where('role_id', Role::where('name', 'Employee')->first()->id)
->whereDoesntHave('customers')
->when($record, function ($query, $record) {
return $query->orWhere('id', $record->employee_id);
})
->pluck('name', 'id');
})

But hold on, what did we do here? Let's break it down:

  • We are passing a closure using the options method.
  • The Closure receives the current record as an argument. This is needed for edit forms where we must include the selected Option.
  • We are fetching all users with the role of Employee who don't have any customers assigned to them.
  • We use the when method to include the selected employee in the list. This is only for edit forms.
  • Finally, we are plucking the name and id columns to create the options list.

Once this is done, the select field will only show employees with no customers assigned to them.

At the same time, we can simplify this code to it's core:

Forms\Components\Select::make('employee_id')
->label('Assigned Employee')
->options(function ($record) {
return User::query()
// Here, we are filtering out a specific relationship.
->whereDoesntHave('customers')
->when($record, function ($query, $record) {
return $query->orWhere('id', $record->employee_id);
})
->pluck('name', 'id');
})

Of course, we can expand this from here to limit how many times the same Option can be selected. It all depends on your query using the options method.


This example is based on our Customer Management CRM

A few of our Premium Examples: