-
-
Notifications
You must be signed in to change notification settings - Fork 86
Relations
Just add ->relation()
to any field and handle the data in the saveFoo()
hook.
Instead of writing default methods to support all Laravel relationships the saveFoo()
hook
gives you total freedom on how you want to manipulate the data before it is being saved.
This way you can define any type of relationship you want.
The relationship fields are ignored in the default save method.
If you do not handle it with the saveFoo()
hook it will be as if it didn't exist in the form at all.
The method is executed after the model is saved.
Define the field
Checkboxes::make('Attach to Events', 'event_ids')//make sure that the name doesn't collide with a model property
->options($this->events)//if using checkboxes read the documentation about integer values
->relation() //tell the component that this field is a relationship
->rules('nullable|array|exists:events,id'),
You can omit FormData
in the method name, if it is an array like form_data.organization.name
the method name becomes saveOrganizationName()
The data is accessed via data_get($relationship_data, 'foo')
or the fields name
property, like $this->foo
, depending on how you setup your form
Add the saveFoo()
method to your component. The relationship will be passed with the same name
as the field.
Example with a field named 'event_ids'
public function saveEventIds($validated_value)
{
// the field data is accessed via the fields name property
$selected_events = $validated_value;
//or depending on your form setup
$selected_events = $this->event_ids;
// save the data
$this->model->...
}
You usually don't have to use the relation()
option for a BelongsTo relationship because you can use a simple select
field.
Example BelongsTo, no->relation() needed.
//Populate a property in the components mount() method to setup the options for the select.
$this->belongsToOptions = //some query()->toArray() as [$key => $value]
//in the fields() method
Select::make('Belongs To', 'some_model_id')
->options($this->belongsToOptions)
->rules([
'required',
'exists:some-table,id',
Rule::in(array_values($this->belongsToOptions))
])
->placeholder("Select a model"),
See the autoSelectSingleArrayValue()
docs ->
In this edit
form example a Location
can be related to many Events
.
We will use a fake model attribute, event_ids
, that does not exist as a column in the database. We use the beforeFormProperties()
method to set existing relations as an appended attribute before form_data
is set.
We also need to get available events
to use as options for the checkboxes.
public function beforeFormProperties()
{
// get existing relations, read the checkboxes docs about integer values
$this->model->event_ids = array_map('strval', optional($this->model->events)->pluck('id')->all());
// set the checkboxes options
$this->events = Event::query()->teamFilter()->select('id', 'name')->get()->pluck('id', 'name')->all();
}
We will use checkboxes
to display available events in the form. We also check if there are any available Events before adding the field to the form. Add the relation()
property to the field.
public function fields()
{
return [
filled($this->events) ? Checkboxes::make('Attach to Events', 'event_ids')
->options($this->events)
->relation()
->placeholder(trans('global.select').' '.trans('crud.event.title_singular'))
->rules('nullable|array|exists:events,id') : null,
];
}
Add the saveFoo()
to the component.
public function saveEventIds($validated_value)
{
//get the options that the user selected via the field name
$selected_events = $validated_value;
//if the user unselected all available options it means we have to detach any existing relations
if (blank($selected_events)) {
$this->model->events()->detach(); //detach all existing relations
} else {
//in this example we scoped the events to the users current team, so we check which events the user is allowed to attach
//this is also a good example on how to validate the submitted data
$allowed_to_sync = filled($selected_events) ? array_intersect($selected_events, array_values($this->events)) : [];
if (filled($allowed_to_sync)) $this->model->events()->sync($selected_events);
}
}
- Installation
- Requirements
- v5 Upgrade Guide
- v6 Upgrade Guide
- v7 Upgrade Guide
- Support
- Quickstart
- Manual installation
- Optional
- Form component
- Field
- Field types
- Example Form
- Blade Components
- Notifications