'Add field text from relationship in laravel nova in ONE form
I'm new on Laravel Nova. I'm trying to build a User form. In this moment I have these models: User, UserDetail
In User I have: email, password, username. In UserDetail I have: Name, Lastname, Gender, Number, etc.
Now I would create One form for user. Why I'm focusing on ONE? Because in my User Resource fields I have:
HasOne::make("UserDetail", "details"),
But For set user detail I have 2 form: One for User data (username, password, email) And after save the user I can set detail.
So I don't want compile 2 different form for 1 resource.
I have found this package, but seems broke:
https://github.com/yassipad/laravel-nova-nested-form/issues/66
And the fields UserDetails doens't shown.
So is there any other way for add text field from relationship and merge in same Form?
Solution 1:[1]
You could solve this by using Laravel's accessors and mutators.
In this example I am only going to add gender
from UserDetail
because I am lazy. So we start with adding a accessor for gender in our User
model
public function details()
{
return $this->hasOne(UserDetail::class);
}
public function getGenderAttribute()
{
return $this->details->gender ?? null;
}
This getter will get the gender from the details or null if no details exist.
Now we add a new field to our User
resource in Nova.
public function fields(Request $request)
{
return [
ID::make()->sortable(),
Gravatar::make(),
Text::make('Name')
->sortable()
->rules('required', 'max:255'),
Text::make('Email'),
Password::make('Password'),
Text::make('Gender')
->rules('required'),
];
}
Going to the create user form, it will look something like this:
Of course this will not make it save it, as it has no idea how to handle the gender
field. For handling this we override fillFields
method.
protected static function fillFields(NovaRequest $request, $model, $fields)
{
// Get all of our user details data
$userDetails = $request->only(['gender']);
// Remove them from the request
$request->request->remove('gender');
$result = parent::fillFields($request, $model, $fields);
// Insert them in the details object after model has been saved.
$result[1][] = function () use ($userDetails, $model){
$model->details()->updateOrCreate(
[],
$userDetails
);
};
return $result;
}
Now we are able to see the gender field as a normal field on the user, and have no need for the UserDetail
resource. To add more fields to be saved in the user details table, we have to add them to our only and remove them from our request. (would make sense to have that in a array)
This method also works when updating a user because we choose to use updateOrCreate
.
A extra note about this approach is that we just introduced a n+1 query, as we are lazy loading the details
relation when trying to get the gender
attribute. To solve this we simply override indexQuery
and add details
to the query builder.
public static function indexQuery(NovaRequest $request, $query)
{
$query->with('details');
return parent::indexQuery($request, $query);
}
Solution 2:[2]
Nova 4 supports now hasOne relation inline form
https://nova.laravel.com/docs/4.0/releases.html#inline-hasone-creation
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Mahen Nakar |