- Basics
- Column Label
- Pivot
- Creating Relationship Object
- Select
- Options
- Placeholder
- Tree
- Horizontal mode
- Preview
- Only Link
- Values Query
- Async Search
- Associated Fields
- Values with Image
- Buttons
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,)
$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.
use App\MoonShine\Resources\CategoryResource;use MoonShine\Laravel\Fields\Relationships\BelongsToMany; BelongsToMany::make( 'Categories', 'categories', resource: CategoryResource::class)
You can omit $resource
if the ModelResource
matches the relationship name.
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')
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')
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")
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)
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)
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'),])
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,)
use App\MoonShine\Resources\CategoryResource;use MoonShine\Laravel\Fields\Relationships\BelongsToMany; BelongsToMany::make('Categories', resource: CategoryResource::class) ->creatable()
You can customize the creation button by passing the button parameter to the method.
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.
use App\MoonShine\Resources\CategoryResource;use MoonShine\Laravel\Fields\Relationships\BelongsToMany; BelongsToMany::make('Categories', resource: CategoryResource::class) ->selectMode()
Options
All select options are available for modification via data attributes:
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)
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)
use App\MoonShine\Resources\CategoryResource;use MoonShine\Laravel\Fields\Relationships\BelongsToMany; BelongsToMany::make('Categories', resource: CategoryResource::class) ->tree('parent_id')
Horizontal mode
The horizontalMode()
method allows you to display values as a horizontal list.
horizontalMode( Closure|bool|null $condition = null, string $minColWidth = '200px', string $maxColWidth = '1fr')
$condition
- (optional) condition for setting the field to horizontal mode,$minColWidth
- (optional) min column width,$maxColWidth
- (optional) max column width.
use App\MoonShine\Resources\CategoryResource;use MoonShine\Laravel\Fields\Relationships\BelongsToMany; BelongsToMany::make('Categories', resource: CategoryResource::class) ->horizontalMode(true, minColWidth: '100px', maxColWidth: '33%')
Preview
By default, in preview, the field will be displayed in a table.
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()
inLine
The inLine()
method allows displaying the field values in a single line.
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.
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 ) )
Only Link
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)
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.
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.
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)
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))
Async Search
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,)
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.
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.
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)
$column
- the field with which the relationship is established,searchQuery
- callback function for filtering values.
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 = '')
$column
- field with the image,$disk
- filesystem disk,$dir
- directory relative to the root of the disk.
use App\MoonShine\Resources\CityResource;use MoonShine\Laravel\Fields\Relationships\BelongsTo; BelongsToMany::make('Cities', resource: CityResource::class) ->withImage('thumb', 'public', 'countries')->selectMode()
Buttons
The buttons()
method allows you to add additional buttons to the BelongsToMany
field.
buttons(array $buttons)
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.
use App\MoonShine\Resources\CategoryResource;use MoonShine\Laravel\Fields\Relationships\BelongsToMany; BelongsToMany::make('Categories', resource: CategoryResource::class) ->withCheckAll()