# Basics
The HasMany field is designed to work with the relation of the same name in Laravel and includes all the basic methods.
To create this field, use the static make()
method.
HasMany::make( Closure|string $label, ?string $relationName = null, Closure|string|null $formatted = null, ?ModelResource $resource = null)
$relationName
- name of the relationship,$resource
- the model resource referenced by the relation.
$label
- label, field header,
The $formatted
parameter is not used in the HasMany
field!
The presence of the model resource referenced by the relation is mandatory!
The resource also needs to be
registered
with the service provider MoonShineServiceProvider in the method
menu()
or resources()
. Otherwise, there will be a 404 error.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', 'comments', resource: new CommentResource()) ];} //...
If you do not specify $relationName
,
then the relation name will be determined automatically based on $label
.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ];} //...
You can omit $resource
if the model resource matches the name of the relationship.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', 'comments') ];} //...
# Fields
The fields()
method allows you to set the fields that will be displayed in the preview.
fields(Fields|Closure|array $fields)
use MoonShine\Fields\Relationships\BelongsTo;use MoonShine\Fields\Relationships\HasMany;use MoonShine\Fields\Text; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->fields([ BelongsTo::make('User'), Text::make('Text'), ]) ];} //...
# Creating a Relationship Object
The creatable()
method allows you to create a new relation object through a modal window.
creatable( Closure|bool|null $condition = null, ?ActionButton $button = null,)
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->creatable() ];} //...
You can customize the create button by passing the button parameter to the method.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->creatable( button: ActionButton::make('Custom button', '') ) ];} //...
# Number of records
The limit()
method allows you to limit the number of records displayed in preview.
limit(int $limit)
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->limit(1) ];} //...
# Link only
The onlyLink()
method will allow you to display the relationship as a link with the number of elements.
onlyLink(?string $linkRelation = null, Closure|bool|null $condition = null)
You can pass optional parameters to the method:
linkRelation
- link to the relationship;-
condition
- closure or boolean value, responsible for displaying the relationship as a link.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->onlyLink() ];} //...
The linkRelation
parameter allows you to create a link to a relation with a parent resource binding.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->onlyLink('comment') ];} //...
The condition
parameter via a closure will allow you to change the display method depending on the conditions.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->onlyLink(condition: function (int $count, Field $field): bool { return $count > 10; }) ];} //...
# Parent ID
If the relationship has a resource, and you want to get the ID of the parent element, then you can use the ResourceWithParent trait.
use MoonShine\Resources\ModelResource;use MoonShine\Traits\Resource\ResourceWithParent; class PostImageResource extends ModelResource{ use ResourceWithParent; //...}
When using a trait, it is necessary to define methods:
protected function getParentResourceClassName(): string{ return PostResource::class;} protected function getParentRelationName(): string{ return 'post';}
To get the parent ID, use the getParentId()
method.
$this->getParentId();
Recipe: saving files HasMany connections in the directory with the parent ID.
# Edit button
The changeEditButton()
method allows you to completely redefine the edit button.
use MoonShine\Fields\Relationships\HasMany; //... HasMany::make('Comments', 'comments', resource: new CommentResource()) ->changeEditButton( ActionButton::make( 'Edit', fn(Comment $comment) => (new CommentResource())->formPageUrl($comment) ) )
# Modal
By default, creating and editing a HasMany field entry occurs in a modal,
The withoutModals()
method allows you to disable this behavior.
use MoonShine\Fields\Relationships\HasMany; //... HasMany::make('Comments', 'comments', resource: new CommentResource()) ->withoutModals()
# Modify
The HasMany field has methods that can be used to modify the buttons, change TableBuilder for preview and form, and change onlyLink button.
The modifyItemButtons()
method allows you to change the view, edit,
deletion and mass deletion.
/** * @param Closure(ActionButton $detail, ActionButton $edit, ActionButton $delete, ActionButton $massDelete, self $field): array $callback */modifyItemButtons(Closure $callback)
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->modifyItemButtons( fn(ActionButton $detail, $edit, $delete, $massDelete, HasMany $ctx) => [$detail]) ) ];} //...
The modifyOnlyLinkButton()
method allows you to change the onlyLink button.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->onlyLink() ->modifyOnlyLinkButton( fn(ActionButton $button, bool $preview) => $button ->when( $preview, fn(ActionButton $btn) => $btn->primary() fn(ActionButton $btn) => $btn->secondary() ) ) ];} //...
modifyCreateButton()
and modifyEditButton()
methods
allow you to change the create and edit buttons.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->modifyCreateButton( fn(ActionButton $button) => $button->setLabel('Custom create button') ) ->modifyEditButton( fn(ActionButton $button) => $button->setLabel('Custom edit button') ) ->creatable(true) ];} //...
The modifyTable()
method allows you to change the TableBuilder for the preview and form.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->modifyTable( fn(TableBuilder $table, bool $preview) => $table ->when($preview, fn(TableBuilder $tbl) => $tbl->customAttributes(['style' => 'background: blue'])) ->unless($preview, fn(TableBuilder $tbl) => $tbl->customAttributes(['style' => 'background: green'])) ) ];} //...
# Advanced
The HasMany field is displayed outside the main resource form by default.
If you need to display relation fields inside the main form,
then you can use the JSON field in the asRelation()
mode.
//... public function fields(): array{ return [ Json::make('Comments', 'comments') ->asRelation(new CommentResource()) //... ]} //...
For more detailed information, please refer to the section Json field .
Using the Template field you can construct a field for HasMany relationships using fluent interface during the declaration process.
For more detailed information, please refer to the section Template field .
In Moonshine you can customize the form page and place HasMany fields in tabs using the Tabs and Tab decorations.
class PostFormPage extends FormPage{ public function components(): array { if(! $this->getResource()->getItemID()) { return parent::components(); } $bottomComponents = $this->getLayerComponents(Layer::BOTTOM); $imagesComponent = collect($bottomComponents)->filter(fn($component) => $component->getName() === 'images')->first(); $commentsComponent = collect($bottomComponents)->filter(fn($component) => $component->getName() === 'comments')->first(); $tabLayer = [ Block::make('', [ Tabs::make([ Tab::make('Edit', $this->mainLayer()), Tab::make('Images', [$imagesComponent]), Tab::make('Comments', [$commentsComponent]) ]) ]) ]; return [ ...$this->getLayerComponents(Layer::TOP), ...$tabLayer, ]; }}
For more details you can read the article Form page customization. Moon Shine 2.0 .