Fields

HasMany

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,
)
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.

 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make(
'Comments',
'comments',
resource: CommentResource::class
)
 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make(
'Comments',
'comments',
resource: CommentResource::class
)

has_many has_many_dark

You can omit the $resource if the ModelResource matches the name of the relation.

use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', 'comments')
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')
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()
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)
fields(FieldsContract|Closure|iterable $fields)
 namespaces
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'),
])
 namespaces
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'),
])

has_many_fields has_many_fields_dark

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,
)
creatable(
Closure|bool|null $condition = null,
?ActionButtonContract $button = null,
)
 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', resource: CommentResource::class)
->creatable()
 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', resource: CommentResource::class)
->creatable()

has_many_creatable has_many_creatable_dark

You can customize the create button by passing the button parameter in the method.

 namespaces
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', '')
)
 namespaces
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)
limit(int $limit)
 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', resource: CommentResource::class)
->limit(1)
 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', resource: CommentResource::class)
->limit(1)

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)
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.

 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', resource: CommentResource::class)
->relatedLink()
 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', resource: CommentResource::class)
->relatedLink()

has_many_link has_many_link_dark

The linkRelation parameter allows you to create a link to the relation with parent resource binding.

 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', resource: CommentResource::class)
->relatedLink('comment')
 namespaces
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.

 namespaces
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;
})
 namespaces
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.

 namespaces
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\Traits\Resource\ResourceWithParent;
 
class PostImageResource extends ModelResource
{
use ResourceWithParent;
 
// ...
}
 namespaces
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';
}
protected function getParentResourceClassName(): string
{
return PostResource::class;
}
 
protected function getParentRelationName(): string
{
return 'post';
}

To get the parent ID, use the getParentId() method.

$this->getParentId();
$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.

 namespaces
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)
)
)
 namespaces
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.

 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', 'comments', resource: CommentResource::class)
->withoutModals()
 namespaces
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
public function searchable(Closure|bool|null $condition = null): static
 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', 'comments', resource: CommentResource::class)
->searchable(false) // disables the search field
 namespaces
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)
/**
* @param Closure(ActionButtonContract $detail, ActionButtonContract $edit, ActionButtonContract $delete, ActionButtonContract $massDelete, static $ctx): array $callback
*/
modifyItemButtons(Closure $callback)
 namespaces
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]
)
 namespaces
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.

 namespaces
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())
)
 namespaces
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.

 namespaces
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)
 namespaces
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.

 namespaces
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']))
)
 namespaces
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.

 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', resource: CommentResource::class)
->redirectAfter(fn(int $parentId) => route('home'))
 namespaces
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.

 namespaces
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)
 namespaces
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)

Adding ActionButtons

indexButtons()

The indexButtons() method allows you to add additional ActionButtons for working with HasMany elements.

 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasMany;
 
HasMany::make('Comments', 'comments', resource: CommentResource::class)
->indexButtons([
ActionButton::make('Custom button')
])
 namespaces
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.

 namespaces
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')
])
 namespaces
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)),
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.

 namespaces
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'),
])
 namespaces
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.