Fields

BelongsToMany

Basics

The BelongsToMany field is designed to work with the same-name relationship in Laravel and includes all Basic Methods.

BelongsToMany::make(
Closure|string $label,
?string $relationName = null,
Closure|string|null $formatted = null,
ModelResource|string|null $resource = null,
)
BelongsToMany::make(
Closure|string $label,
?string $relationName = null,
Closure|string|null $formatted = null,
ModelResource|string|null $resource = null,
)
  • $label - label, field title,
  • $relationName - name of the relationship,
  • $formatted - closure or field in the related table to display values,
  • $resource - ModelResource that the relationship references.

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\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make(
'Categories',
'categories',
resource: CategoryResource::class
)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make(
'Categories',
'categories',
resource: CategoryResource::class
)

belongs_to_many belongs_to_many_dark

You can omit $resource if the ModelResource matches the relationship name.

use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', 'categories')
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', 'categories')

If $relationName is not specified, then the relationship name will be determined automatically based on $label (following camelCase rules).

use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories')
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories')

By default, the value is displayed using the field in the related table specified by the $column property in the model resource. The $formatted argument allows overriding this.

use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make(
'Categories',
'categories',
formatted: 'name'
)
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make(
'Categories',
'categories',
formatted: 'name'
)

If you need to specify a more complex value for display, then you can pass a callback function in the $formatted argument.

use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make(
'Categories',
'categories',
fn($item) => "$item->id. $item->title"
)
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make(
'Categories',
'categories',
fn($item) => "$item->id. $item->title"
)

Column Label

By default, the table column header uses the $title property specified in the ModelResource relationship. The columnLabel() method allows overriding the header.

columnLabel(string $label)
columnLabel(string $label)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->columnLabel('Title')
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->columnLabel('Title')

Pivot

The fields() method is used to implement pivot fields in the BelongsToMany relationship.

fields(FieldsContract|Closure|iterable $fields)
fields(FieldsContract|Closure|iterable $fields)
 namespaces
use App\MoonShine\Resources\ContactResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Text;
 
BelongsToMany::make(
'Contacts',
resource: ContactResource::class
)
->fields([
Text::make('Contact', 'text'),
])
 namespaces
use App\MoonShine\Resources\ContactResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Text;
 
BelongsToMany::make(
'Contacts',
resource: ContactResource::class
)
->fields([
Text::make('Contact', 'text'),
])

belongs_to_many_pivot belongs_to_many_pivot_dark

In the relationship, you must specify which pivot fields are used in the intermediate table! For more details, see the official documentation Laravel.

Creating Relationship Object

The creatable() method allows you to create a new relationship object via a modal window.

creatable(
Closure|bool|null $condition = null,
?ActionButton $button = null,
)
creatable(
Closure|bool|null $condition = null,
?ActionButton $button = null,
)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->creatable()
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->creatable()

belongs_to_many_creatable belongs_to_many_creatable_dark

You can customize the creation button by passing the button parameter to the method.

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Components\ActionButton;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->creatable(
button: ActionButton::make('Custom button', '')
)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Components\ActionButton;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->creatable(
button: ActionButton::make('Custom button', '')
)

Select

The BelongsToMany field can be displayed as a dropdown list. To do this, you need to use the selectMode() method.

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->selectMode()
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->selectMode()

belongs_to_many_select belongs_to_many_select_dark

Options

All select options are available for modification via data attributes:

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->selectMode()
->customAttributes([
'data-max-item-count' => 2
])
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->selectMode()
->customAttributes([
'data-max-item-count' => 2
])

For more detailed information, please refer to Choices.

Placeholder

The placeholder() method allows you to set the placeholder attribute for the field.

placeholder(string $value)
placeholder(string $value)
BelongsToMany::make('Countries', 'countries')
->nullable()
->placeholder('Countries')
BelongsToMany::make('Countries', 'countries')
->nullable()
->placeholder('Countries')

The placeholder() method is only used if the field is displayed as a dropdown list selectMode()!

Tree

The tree() method allows values to be displayed in a tree format with checkboxes, for example, for categories that have nesting. The method requires you to pass the column in the database by which the tree will be built.

tree(string $parentColumn)
tree(string $parentColumn)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->tree('parent_id')
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->tree('parent_id')

belongs_to_many_tree belongs_to_many_tree_dark

Preview

By default, in preview, the field will be displayed in a table.

belongs_to_many_preview belongs_to_many_preview_dark

To change the display in preview, you can use the following methods.

onlyCount

The onlyCount() method allows you to display only the number of selected values in preview.

BelongsToMany::make('Categories', resource: CategoryResource::class)
->onlyCount()
BelongsToMany::make('Categories', resource: CategoryResource::class)
->onlyCount()

belongs_to_many_preview_count belongs_to_many_preview_count_dark

inLine

The inLine() method allows displaying the field values in a single line.

inLine(string $separator = '', Closure|bool $badge = false, ?Closure $link = null)
inLine(string $separator = '', Closure|bool $badge = false, ?Closure $link = null)

You can pass optional parameters to the method:

  • separator - separator between items,
  • badge - closure or boolean value responsible for displaying items as badges,
  • $link - closure that should return url links or components.

When passing a boolean value true to the badge parameter, the Primary color will be used. To change the color of the displayed badge, use a closure and return the Badge::make() component.

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Components\Badge;
use MoonShine\UI\Components\Link;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->inLine(
separator: ' ',
badge: fn($model, $value) => Badge::make((string) $value, 'primary'),
link: fn(Property $property, $value, $field) => (string) Link::make(
app(CategoryResource::class)->getDetailPageUrl($property->id),
$value
)
)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Components\Badge;
use MoonShine\UI\Components\Link;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->inLine(
separator: ' ',
badge: fn($model, $value) => Badge::make((string) $value, 'primary'),
link: fn(Property $property, $value, $field) => (string) Link::make(
app(CategoryResource::class)->getDetailPageUrl($property->id),
$value
)
)

belongs_to_many_preview_in_line belongs_to_many_preview_in_line_dark

The relatedLink() method will display the relationship as a link with a count of elements. The link will lead to the IndexPage of the child resource from the HasMany relationship, which will show only 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 relationship,
  • condition - closure or boolean value responsible for displaying the relationship as a link.

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

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->relatedLink('category')
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->relatedLink('category')

The condition parameter through a closure will allow changing the display method depending on conditions.

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->relatedLink(condition: function (int $count, Field $field): bool {
return $count > 10;
})
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->relatedLink(condition: function (int $count, Field $field): bool {
return $count > 10;
})

Values Query

The valuesQuery() method allows you to modify the query for retrieving values.

valuesQuery(Closure $callback)
valuesQuery(Closure $callback)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use Illuminate\Contracts\Database\Eloquent\Builder;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
 
BelongsToMany::make('Categories', 'categories', resource: CategoryResource::class)
->valuesQuery(fn(Builder $query, Field $field) => $query->where('active', true))
 namespaces
use App\MoonShine\Resources\CategoryResource;
use Illuminate\Contracts\Database\Eloquent\Builder;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
 
BelongsToMany::make('Categories', 'categories', resource: CategoryResource::class)
->valuesQuery(fn(Builder $query, Field $field) => $query->where('active', true))

To implement asynchronous search for values, use the asyncSearch() method.

asyncSearch(
string $column = null,
?Closure $searchQuery = null,
?Closure $formatted = null,
?string $associatedWith = null,
int $limit = 15,
?string $url = null,
)
asyncSearch(
string $column = null,
?Closure $searchQuery = null,
?Closure $formatted = null,
?string $associatedWith = null,
int $limit = 15,
?string $url = null,
)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', 'categories', resource: CategoryResource::class)
->asyncSearch()
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', 'categories', resource: CategoryResource::class)
->asyncSearch()

The search will be performed by the relationship resource column. By default, column=id.

You can pass parameters to the asyncSearch() method:

  • $column - the field to search by,
  • $searchQuery - callback function for filtering values,
  • $formatted - callback function for customizing the output,
  • $associatedWith - field to establish a relationship,
  • $limit - number of elements in the search results,
  • $url - url for processing the asynchronous request.
 namespaces
use App\MoonShine\Resources\CountryResource;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
 
BelongsToMany::make('Countries', 'countries', resource: CountryResource::class)
->asyncSearch(
'title',
10,
searchQuery: function (Builder $query, Request $request, Field $field) {
return $query->where('id', '!=', 2);
},
formatted: function ($country, Field $field) {
return $country->id . ' | ' . $country->title;
},
'https://moonshine-laravel.com/async'
)
 namespaces
use App\MoonShine\Resources\CountryResource;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
 
BelongsToMany::make('Countries', 'countries', resource: CountryResource::class)
->asyncSearch(
'title',
10,
searchQuery: function (Builder $query, Request $request, Field $field) {
return $query->where('id', '!=', 2);
},
formatted: function ($country, Field $field) {
return $country->id . ' | ' . $country->title;
},
'https://moonshine-laravel.com/async'
)

When constructing the query in searchQuery(), you can use the current form values. To do this, pass Request to the callback function.

 namespaces
use App\MoonShine\Resources\CityResource;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
use MoonShine\UI\Fields\Select;
 
Select::make('Country', 'country_id'),
 
BelongsToMany::make('Cities', 'cities', resource: CityResource::class)
->asyncSearch(
'title',
searchQuery: function (Builder $query, Request $request, Field $field): Builder {
return $query->where('country_id', $request->get('country_id'));
}
)
 namespaces
use App\MoonShine\Resources\CityResource;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
use MoonShine\UI\Fields\Select;
 
Select::make('Country', 'country_id'),
 
BelongsToMany::make('Cities', 'cities', resource: CityResource::class)
->asyncSearch(
'title',
searchQuery: function (Builder $query, Request $request, Field $field): Builder {
return $query->where('country_id', $request->get('country_id'));
}
)

Queries should be set up using the asyncSearch() method. Do not use valuesQuery()!

Associated Fields

To establish a relationship of select values between fields, you can use the associatedWith() method.

associatedWith(string $column, ?Closure $searchQuery = null)
associatedWith(string $column, ?Closure $searchQuery = null)
  • $column - the field with which the relationship is established,
  • searchQuery - callback function for filtering values.
 namespaces
use App\MoonShine\Resources\CityResource;
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
 
BelongsToMany::make('Cities', 'cities', resource: CityResource::class)
->associatedWith('country_id')
 namespaces
use App\MoonShine\Resources\CityResource;
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
 
BelongsToMany::make('Cities', 'cities', resource: CityResource::class)
->associatedWith('country_id')

For more complex configurations, you can use asyncSearch().

Values with Image

The withImage() method allows you to add an image to the value.

withImage(
string $column,
string $disk = 'public',
string $dir = ''
)
withImage(
string $column,
string $disk = 'public',
string $dir = ''
)
  • $column - field with the image,
  • $disk - filesystem disk,
  • $dir - directory relative to the root of the disk.
 namespaces
use App\MoonShine\Resources\CityResource;
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
 
BelongsToMany::make('Cities', resource: CityResource::class)
->withImage('thumb', 'public', 'countries')->selectMode()
 namespaces
use App\MoonShine\Resources\CityResource;
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
 
BelongsToMany::make('Cities', resource: CityResource::class)
->withImage('thumb', 'public', 'countries')->selectMode()

with_image belongs_to_image_dark

Buttons

The buttons() method allows you to add additional buttons to the BelongsToMany field.

buttons(array $buttons)
buttons(array $buttons)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\UI\Components\ActionButton;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->buttons([
ActionButton::make('Check all', '')
->onClick(fn() => 'checkAll', 'prevent'),
 
ActionButton::make('Uncheck all', '')
->onClick(fn() => 'uncheckAll', 'prevent')
])
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\UI\Components\ActionButton;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->buttons([
ActionButton::make('Check all', '')
->onClick(fn() => 'checkAll', 'prevent'),
 
ActionButton::make('Uncheck all', '')
->onClick(fn() => 'uncheckAll', 'prevent')
])

withCheckAll

The withCheckAll() method allows you to add a checkAll button to the BelongsToMany field, similar to the previous example.

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->withCheckAll()
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->withCheckAll()