How can I access relationships inside the disableOptionWhen

How can I access relationships inside the disableOptionWhen callback exactly the same way I do in getOptionLabelFromRecordUsing? Perhaps I’m approaching this the wrong way. I just want to disable the shift options when the shift->orders relationship has a status other than OrderStatus::New, OrderStatus::Completed, or OrderStatus::Cancelled. But the disableOptionWhen method doesn’t let me access $record->orders; it’s using the Order form model instead of the Shift relationship.
Forms\Components\Select::make('shift_id')
->label(__('Select a shift'))
->relationship('shift', 'id', function ($query) {
return $query->where('status', ShiftStatus::Active)->with(['driver', 'car', 'orders']);
})
->getOptionLabelFromRecordUsing(
fn ($record) =>
"{$record->driver->first_name} {$record->driver->last_name}" .
" - " .
"{$record->car->brand} {$record->car->model}"
)
->disableOptionWhen(function ($record) {
//Not Working (((
return $record->orders
->whereNotIn('status', [
OrderStatus::New,
OrderStatus::Completed,
OrderStatus::Cancelled,
])
->isNotEmpty();
})
->searchable()
Forms\Components\Select::make('shift_id')
->label(__('Select a shift'))
->relationship('shift', 'id', function ($query) {
return $query->where('status', ShiftStatus::Active)->with(['driver', 'car', 'orders']);
})
->getOptionLabelFromRecordUsing(
fn ($record) =>
"{$record->driver->first_name} {$record->driver->last_name}" .
" - " .
"{$record->car->brand} {$record->car->model}"
)
->disableOptionWhen(function ($record) {
//Not Working (((
return $record->orders
->whereNotIn('status', [
OrderStatus::New,
OrderStatus::Completed,
OrderStatus::Cancelled,
])
->isNotEmpty();
})
->searchable()
15 Replies
Dennis Koch
Dennis Koch3mo ago
What do you mean by "it's using the Order Form model"? Alternative approach: Instead of querying every row in the disabledWhen callback, I'd rather get the orders_count with that constraint for every row, then you can check whether $record->orders_count > 0
cepairda
cepairdaOP3mo ago
getOptionLabelFromRecordUsing(fn ($record) - Here $record is the type of Shift(relationship) model. But in disableOptionWhen(function($record) method - $record is the type of Order - this is the main scheme, resource , I expected to access the Shift relationship to check each item I would like to do as you suggest, good solution. But $record returns the model of the main scheme, I expected that it would be the model of my relationship
Dennis Koch
Dennis Koch3mo ago
Ah I guess that’s expected because it’s the option and you check each option. Try ($livewire) => $livewire->record->shift instead. That might not have the relationship loaded though so it might load that again.
cepairda
cepairdaOP3mo ago
I'm trying to explain that the method getOptionLabelFromRecordUsing(fn ($record) As expected, $record is our relation, and we work with it right away, and I have access to each option. I expect the same from disableOptionWhen, I want to work with each option through $record. For Example IN - getOptionLabelFromRecordUsing - $record ($record - Type Shift) IN - disableOptionWhen - $record ($record - Type Order or null when create) $livewire->record->shift it doesn't work when creating, Attempt to read property "shift" on null. This is expected, since the record has not been created yet
Dennis Koch
Dennis Koch3mo ago
Then just add a null-safe operator: $livewire->record?->shift ?? false
cepairda
cepairdaOP3mo ago
I think you misunderstood me. On the creation page, this should also work and make shifts inactive. It works but it doesn't suit me because of the problem N + 1. I would like to be able to access Shift via $record or any other solution to avoid N + 1 problem
->disableOptionWhen(function (mixed $value): bool {

$shift = Shift::with('orders')
->find($value);

if (! $shift) {
return false;
}

return $shift->orders
->whereNotIn('status', [
OrderStatus::New->value,
OrderStatus::Completed->value,
OrderStatus::Cancelled->value,
])
->isNotEmpty();
})
->disableOptionWhen(function (mixed $value): bool {

$shift = Shift::with('orders')
->find($value);

if (! $shift) {
return false;
}

return $shift->orders
->whereNotIn('status', [
OrderStatus::New->value,
OrderStatus::Completed->value,
OrderStatus::Cancelled->value,
])
->isNotEmpty();
})
Dennis Koch
Dennis Koch3mo ago
Hm. I just reread your first example and I think it's weird, that $record is of type Order and not Shift since all the options are Shifts ... 🤔
cepairda
cepairdaOP3mo ago
Yes, you understood correctly, on the creation page $record = null, on the editing page Order. Although I have a shift relationship and I expected to get this type - Shift
cepairda
cepairdaOP3mo ago
I have version 3.* But here's what I found interesting in the documentation for version 4.*
No description
No description
Dennis Koch
Dennis Koch3mo ago
Okay. So this is on a EditOrder page, right? Then it makes sense. I am not sure whether there is a better way to solve the N + 1 issue. You could preload that data on mount, save it to a protected property and reuse it in that function.
cepairda
cepairdaOP3mo ago
This is needed on both the creation page and the editing page. But first I want to make a working creation page In the documentation of version 4 it is written that in $record model of the scheme, when the expected behavior was - $record equals my relation
Dennis Koch
Dennis Koch3mo ago
Yes, I guess there is some kind of limitation, that why you only get the option values.
cepairda
cepairdaOP3mo ago
Where can I write to consider this possibility in future updates? I think this is a useful feature. For example, I want to show a record in the list, but if $record ->status is not equal to a certain value, then disable it
Dennis Koch
Dennis Koch3mo ago
You can open a Discussion on GitHub, but I think it's quite niche. Did you try the workaround via mount() method I mentioned above?
cepairda
cepairdaOP3mo ago
I haven't tried it yet, but it turns out I'll be making the same sql query twice, in Mount and in relationship. Still haven't found a solution to this problem 😦

Did you find this page helpful?