- Basics
- Fields
- Creating a relationship object
- Record count
- Only link
- Parent ID
- Edit button
- Modal window
- Modification
- Display
- Active Actions
- Adding ActionButtons
- Advanced usage
Basics
The HasMany
field is designed to work with the same-name relationship in Laravel and includes all Basic methods.
HasMany::make( Closure|string $label, ?string $relationName = null, Closure|string|null $formatted = null, ModelResource|string|null $resource = null,)
$label
- label, header of the field,$relationName
- name of the relation,$resource
-ModelResource
that the relation points to.
The $formatted
parameter is not used in the HasMany
field!
Having a ModelResource
that the relationship refers to is mandatory.
The resource must also be registered in the MoonShineServiceProvider
service provider in the $core->resources()
method.
Otherwise, there will be a 500 error.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make( 'Comments', 'comments', resource: CommentResource::class)
You can omit the $resource
if the ModelResource
matches the name of the relation.
use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', 'comments')
If you do not specify $relationName
, then the name of the relation will be determined automatically based on $label
(following camelCase rules).
use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments')
By default, the field is displayed outside the main form.
If you want to change this behavior and display it inside the main form, use the disableOutside()
method.
use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments')->disableOutside()
Fields
The fields()
method allows you to set the fields that will be displayed in the preview.
fields(FieldsContract|Closure|iterable $fields)
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\BelongsTo;use MoonShine\Laravel\Fields\Relationships\HasMany;use MoonShine\UI\Fields\Text; HasMany::make('Comments', resource: CommentResource::class) ->fields([ BelongsTo::make('User'), Text::make('Text'), ])
Creating a relationship object
The creatable()
method allows you to create a new relationship object through a modal window.
creatable( Closure|bool|null $condition = null, ?ActionButtonContract $button = null,)
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', resource: CommentResource::class) ->creatable()
You can customize the create button by passing the button parameter in the method.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany;use MoonShine\UI\Components\ActionButton; HasMany::make('Comments', resource: CommentResource::class) ->creatable( button: ActionButton::make('Custom button', '') )
Record count
The limit()
method allows you to limit the number of records displayed in the preview.
limit(int $limit)
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', resource: CommentResource::class) ->limit(1)
Only link
The relatedLink()
method allows you to display the relationship as a link with the count of elements.
The link will lead to the IndexPage of the child resource from the HasMany
relationship, only showing those data elements.
relatedLink(?string $linkRelation = null, Closure|bool $condition = null)
You can pass optional parameters to the method:
linkRelation
- link to the relation,condition
- closure or boolean value responsible for displaying the relation as a link.
Don’t forget to add the relation to the $with
property of the resource.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', resource: CommentResource::class) ->relatedLink()
The linkRelation
parameter allows you to create a link to the relation with parent resource binding.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', resource: CommentResource::class) ->relatedLink('comment')
The condition
parameter through a closure allows you to change the display method based on conditions.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany;use MoonShine\UI\Fields\Field; HasMany::make('Comments', resource: CommentResource::class) ->relatedLink(condition: function (int $count, Field $field): bool { return $count > 10; })
Parent ID
If the relation has a resource, and you want to get the ID of the parent element, you can use the ResourceWithParent
trait.
use MoonShine\Laravel\Resources\ModelResource;use MoonShine\Traits\Resource\ResourceWithParent; class PostImageResource extends ModelResource{ use ResourceWithParent; // ...}
When using the trait, you need to define the 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 of HasMany
relations in the directory with the parent ID.
Edit button
The changeEditButton()
method allows you to completely override the edit button.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany;use MoonShine\UI\Components\ActionButton; HasMany::make('Comments', 'comments', resource: CommentResource::class) ->changeEditButton( ActionButton::make( 'Edit', fn(Comment $comment) => app(CommentResource::class)->formPageUrl($comment) ) )
Modal window
By default, creating and editing a record in the HasMany
field occurs in a modal window; the withoutModals()
method allows you to disable this behavior.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', 'comments', resource: CommentResource::class) ->withoutModals()
Modification
The HasMany
field has methods that can be used to modify buttons, change the TableBuilder
for preview and form, as well as change the relatedLink button.
searchable()
By default, a search field is available on the form page for the HasMany
field.
To disable it, you can use the searchable()
method.
public function searchable(Closure|bool|null $condition = null): static
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', 'comments', resource: CommentResource::class) ->searchable(false) // disables the search field
modifyItemButtons()
The modifyItemButtons()
method allows you to change the view, edit, delete, and mass delete buttons.
/** * @param Closure(ActionButtonContract $detail, ActionButtonContract $edit, ActionButtonContract $delete, ActionButtonContract $massDelete, static $ctx): array $callback */modifyItemButtons(Closure $callback)
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany;use MoonShine\UI\Components\ActionButton; HasMany::make('Comments', resource: CommentResource::class) ->modifyItemButtons( fn(ActionButton $detail, $edit, $delete, $massDelete, HasMany $ctx) => [$detail] )
modifyRelatedLink()
The modifyRelatedLink()
method allows you to change the relatedLink button.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany;use MoonShine\UI\Components\ActionButton; HasMany::make('Comments', resource: CommentResource::class) ->relatedLink() ->modifyRelatedLink( fn(ActionButton $button, bool $preview) => $button ->when($preview, fn(ActionButton $btn) => $btn->primary()) ->unless($preview, fn(ActionButton $btn) => $btn->secondary()) )
modifyCreateButton() / modifyEditButton()
The modifyCreateButton()
and modifyEditButton()
methods allow you to change the create and edit buttons.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany;use MoonShine\UI\Components\ActionButton; HasMany::make('Comments', resource: CommentResource::class) ->modifyCreateButton( fn(ActionButton $button) => $button->setLabel('Custom create button') ) ->modifyEditButton( fn(ActionButton $button) => $button->setLabel('Custom edit button') ) ->creatable(true)
modifyTable()
The modifyTable()
method allows you to change the TableBuilder
for preview and form.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany;use MoonShine\UI\Components\Table\TableBuilder; HasMany::make('Comments', resource: CommentResource::class) ->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'])) )
Redirect after modification
The redirectAfter()
method allows for redirection after saving/adding/deleting.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', resource: CommentResource::class) ->redirectAfter(fn(int $parentId) => route('home'))
Modify QueryBuilder
The modifyBuilder()
method allows you to modify the query through QueryBuilder.
use App\MoonShine\Resources\CommentResource;use Illuminate\Database\Eloquent\Relations\Relation;use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', resource: CommentResource::class) ->modifyBuilder(fn(Relation $query, HasMany $ctx) => $query)
Display
Display inside Tabs
By default, relationship fields in MoonShine are displayed at the bottom, separately from the form, and follow one after another. To change the display of the field and add it to Tabs
, you can use the tabMode()
method.
tabMode(Closure|bool|null $condition = null)
In the following example, a Tabs component with two tabs, Comments and Covers, will be created.
use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', 'comments', resource: CommentResource::class) ->tabMode(),HasMany::make('Covers', 'covers', resource: CoverResource::class) ->tabMode()
tabMode will not work when using the disableOutside()
method
Display inside a modal window
To display a HasMany field in a modal window that is triggered by a button, you can use the modalMode()
method.
public function modalMode( Closure|bool|null $condition = null, ?Closure $modifyButton = null, ?Closure $modifyModal = null)
In this example, instead of a table, there will now be an ActionButton that triggers a Modal.
use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', 'comments', resource: CommentResource::class) ->modalMode(),
To modify the ActionButton
and Modal
, you can use the method parameters $modifyButton
and $modifyModal
, into which you can pass a closure.
use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', 'comments', resource: CommentResource::class) ->modalMode( modifyButton: function (ActionButtonContract $button, HasMany $ctx) { $button->warning(); return $button; }, modifyModal: function (Modal $modal, ActionButtonContract $ctx) { $modal->autoClose(false); return $modal; } )
Active Actions
It is possible to quickly turn enable/disable certain actions within the scope of HasMany
.
The activeActions()
method explicitly sets the list of available actions.
HasMany::make('Comments') ->activeActions( Action::VIEW, Action::UPDATE, )
The withoutActions()
method allows you to exclude individual actions.
HasMany::make('Comments') ->withoutActions( Action::VIEW )
Adding ActionButtons
indexButtons()
The indexButtons()
method allows you to add additional ActionButtons
for working with HasMany
elements.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany; HasMany::make('Comments', 'comments', resource: CommentResource::class) ->indexButtons([ ActionButton::make('Custom button') ])
formButtons()
The formButtons()
method allows you to add additional ActionButtons
inside the form when creating or editing a HasMany
element.
use App\MoonShine\Resources\CommentResource;use MoonShine\Laravel\Fields\Relationships\HasMany;use MoonShine\UI\Components\ActionButton; HasMany::make('Comments', 'comments', resource: CommentResource::class) ->formButtons([ ActionButton::make('Custom form button') ])
Advanced usage
Location of the field
The field is used only within CRUD pages, as it retrieves the resource and page from the URL.
However, you can also use it on other pages by specifying its location with the nowOn()
method.
HasMany::make('Comments', resource: CommentResource::class) ->creatable() ->nowOn(page: $resource->getFormPage(), resource: $resource, params: ['resourceItem' => $item->getKey()]) ->fillCast($item, new ModelCaster(Article::class)),
Relation through RelationRepeater field
The HasMany
field is displayed outside the main resource form by default.
If you need to display the relation fields inside the main form, you can use the RelationRepeater
field.
For more detailed information, refer to the RelationRepeater field.
use MoonShine\UI\Fields\Text;use MoonShine\Laravel\Fields\Relationships\RelationRepeater; RelationRepeater::make('Characteristics', 'characteristics') ->fields([ ID::make(), Text::make('Name', 'name'), Text::make('Value', 'value'), ])
Relation through Template field
Using the Template
field, you can build a field for HasMany
relationships using a fluent interface during declaration.
For more detailed information, refer to the Template field.