MorphToSelect with one type

I'm building multiple forms that all write to the same subject morph on the same model. But each form has it's own specific type that needs to be set as the subject. What I'm looking for is a way to set the morph type by default and hide the select field for type, as it's already known. Is this possible?
13 Replies
Dan Harrin
Dan Harrin2y ago
use a normal Select on subject_id instead of a MorphToSelect? and then before you save fill in the subject_type as it's known
bwubs
bwubsOP2y ago
when I do that I get an error that the selected option is not correct
Dan Harrin
Dan Harrin2y ago
what error
bwubs
bwubsOP2y ago
A validation error that the subject doesn't exists
bwubs
bwubsOP2y ago
Dan Harrin
Dan Harrin2y ago
what validation rule are you using
bwubs
bwubsOP2y ago
none
Dan Harrin
Dan Harrin2y ago
please send the code
bwubs
bwubsOP2y ago
Of the whole form? It's quite a complex one The field is this:
private function getLocationField(): Select
{
return Select::make('subject_id')->label(__('Location'))
->relationship('subject', 'name', fn() => Location::query())
->visible(fn ($get) => $get('type') === LocationTask::getName());
}

private function getLocationField(): Select
{
return Select::make('subject_id')->label(__('Location'))
->relationship('subject', 'name', fn() => Location::query())
->visible(fn ($get) => $get('type') === LocationTask::getName());
}

When I use it as above, it sometimes submits the form, but the relationship is not set in the form and sometimes gives an validation error that the given location does not exists. What I think that's happening is that it tries to load the related relation, but because of it being an morph, it thinks the relations is with itself somehow? Because, when i remove the third argument from ->relationship() it shows other models that are of the same type as the one I'm making in the form.
Dan Harrin
Dan Harrin2y ago
replace relationship() with your own options() array
bwubs
bwubsOP2y ago
like this?
return Select::make('subject_id')->label(__('Location'))
->options(Location::query()->select(['id', 'name'])->get()->mapWithKeys(fn(Location $location) => [$location->id => $location->name]))
->visible(fn($get) => $get('type') === LocationTask::getName());
return Select::make('subject_id')->label(__('Location'))
->options(Location::query()->select(['id', 'name'])->get()->mapWithKeys(fn(Location $location) => [$location->id => $location->name]))
->visible(fn($get) => $get('type') === LocationTask::getName());
Yes, this seems to work! This is the complete code now:
private function getLocationField(): array
{
return [
Select::make('subject_id')->label(__('Location'))
->options(Location::query()->select(['id', 'name'])->get()->mapWithKeys(fn(Location $location) => [$location->id => $location->name]))
->visible(fn($get) => $get('type') === LocationTask::getName()),

Hidden::make('subject_type')->default((new Location())->getMorphClass())
];
}
private function getLocationField(): array
{
return [
Select::make('subject_id')->label(__('Location'))
->options(Location::query()->select(['id', 'name'])->get()->mapWithKeys(fn(Location $location) => [$location->id => $location->name]))
->visible(fn($get) => $get('type') === LocationTask::getName()),

Hidden::make('subject_type')->default((new Location())->getMorphClass())
];
}
It works great tothether with the hidden input
Dan Harrin
Dan Harrin2y ago
i wouldnt use a hidden input you should add this type on the backend before the data is saved otherwise it is insecure
bwubs
bwubsOP2y ago
Good point
Want results from more Discord servers?
Add your server