Fields

BelongsTo

Basics

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

To create this field, use the static method make().

BelongsTo::make( Closure|string $label, ?string $relationName = null, Closure|string|null $formatted = null, ModelResource|string|null $resource = null, )
BelongsTo::make(
Closure|string $label,
?string $relationName = null,
Closure|string|null $formatted = null,
ModelResource|string|null $resource = null,
)
  • $label - the label, the title of the field,
  • $relationName - the name of the relation,
  • $formatted - a closure or field in the related table for displaying values,
  • $resource - the model resource that the relationship refers to.

The model resource 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 (Resource is required for MoonShine\Laravel\Fields\Relationships\BelongsTo...).

use MoonShine\Laravel\Fields\Relationships\BelongsTo; BelongsTo::make('Country', 'country', resource: CountryResource::class)
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
 
BelongsTo::make('Country', 'country', resource: CountryResource::class)

belongs_to

belongs_to_dark

If $relationName is not specified, the relation name will be determined automatically based on $label.

BelongsTo::make('Country', resource: CountryResource::class)
BelongsTo::make('Country', resource: CountryResource::class)

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

class CountryResource extends ModelResource { // ... } // ... BelongsTo::make('Country', 'country')
class CountryResource extends ModelResource
{
// ...
}
// ...
BelongsTo::make('Country', 'country')

If you do not specify $relationName, the name of the relationship will be determined automatically based on $label (by camelCase rules).

class CountryResource extends ModelResource { // ... } // ... BelongsTo::make('Country')
class CountryResource extends ModelResource
{
// ...
}
// ...
BelongsTo::make('Country')

By default, the field used to display the value is the one specified by the $column property in the model resource. The $formatted argument allows overriding the $column property.

namespace App\MoonShine\Resources; use MoonShine\Laravel\Resources\ModelResource; class CountryResource extends ModelResource { public string $column = 'title'; } // ... BelongsTo::make( 'Country', 'country', formatted: 'name' )
namespace App\MoonShine\Resources;
 
use MoonShine\Laravel\Resources\ModelResource;
 
class CountryResource extends ModelResource
{
public string $column = 'title';
}
// ...
BelongsTo::make(
'Country',
'country',
formatted: 'name'
)

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

BelongsTo::make( 'Country', 'country', fn($item) => "$item->id. $item->title" )
BelongsTo::make(
'Country',
'country',
fn($item) => "$item->id. $item->title"
)

If you need to change the column when working with models, use the onAfterFill method.

BelongsTo::make( 'Category', resource: CategoryResource::class )->afterFill(fn($field) => $field->setColumn('changed_category_id'))
BelongsTo::make(
'Category',
resource: CategoryResource::class
)->afterFill(fn($field) => $field->setColumn('changed_category_id'))

Default Value

You can use the default() method if you need to specify a default value for the field.

default(mixed $default)
default(mixed $default)

You must pass a model object as the default value.

use App\Models\Country; use MoonShine\Laravel\Fields\Relationships\BelongsTo; BelongsTo::make('Country', resource: CategoryResource::class) ->default(Country::find(1))
use App\Models\Country;
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
 
BelongsTo::make('Country', resource: CategoryResource::class)
->default(Country::find(1))

Nullable

As with all fields, if you need to store NULL, you should add the nullable() method.

nullable(Closure|bool|null $condition = null)
nullable(Closure|bool|null $condition = null)
BelongsTo::make('Country', resource: CategoryResource::class) ->nullable()
BelongsTo::make('Country', resource: CategoryResource::class)
->nullable()

select_nullable

select_nullable_dark

MoonShine is a very convenient and functional tool. However, to use it, you need to be confident in the basics of Laravel.

Don't forget to specify in the database table that the field can accept a Null value.

Placeholder

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

placeholder(string $value)
placeholder(string $value)
BelongsTo::make('Country', 'country') ->nullable() ->placeholder('Country')
BelongsTo::make('Country', 'country')
->nullable()
->placeholder('Country')

Searching Values

If you need to search among values, you must add the searchable() method.

use MoonShine\Laravel\Fields\Relationships\BelongsTo; use App\MoonShine\Resources\CountryResource; BelongsTo::make('Country', 'country', resource: CountryResource::class) ->searchable()
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
use App\MoonShine\Resources\CountryResource;
 
BelongsTo::make('Country', 'country', resource: CountryResource::class)
->searchable()

Creating Relation Object

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

creatable( Closure|bool|null $condition = null, ?ActionButton $button = null, )
creatable(
Closure|bool|null $condition = null,
?ActionButton $button = null,
)
BelongsTo::make('Author', resource: AuthorResource::class) ->creatable()
BelongsTo::make('Author', resource: AuthorResource::class)
->creatable()

belongs_to_creatable

belongs_to_creatable_dark

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

BelongsTo::make('Author', resource: AuthorResource::class) ->creatable( button: ActionButton::make('Custom button', '') )
BelongsTo::make('Author', resource: AuthorResource::class)
->creatable(
button: ActionButton::make('Custom button', '')
)

Query for Values

The valuesQuery() method allows you to change the query to retrieve values.

valuesQuery(Closure $callback)
valuesQuery(Closure $callback)
use Illuminate\Contracts\Database\Eloquent\Builder; use MoonShine\Laravel\Fields\Relationships\BelongsTo; BelongsTo::make('Category', 'category', resource: CategoryResource::class) ->valuesQuery(fn(Builder $query, Field $field) => $query->where('active', true))
use Illuminate\Contracts\Database\Eloquent\Builder;
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
 
BelongsTo::make('Category', 'category', resource: CategoryResource::class)
->valuesQuery(fn(Builder $query, Field $field) => $query->where('active', true))

To implement asynchronous value search, 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,
)
BelongsTo::make('Country', 'country', resource: CategoryResource::class) ->asyncSearch()
BelongsTo::make('Country', 'country', resource: CategoryResource::class)
->asyncSearch()

The search will be carried out by the field specified for the resource column. By default column=id.

You can pass parameters to the asyncSearch() method:

  • $column - the field by which the search is conducted,
  • $searchQuery - a callback function for filtering values,
  • $formatted - a callback function for customizing output,
  • $associatedWith - the field with which the association is established,
  • $limit - the number of items in the search results,
  • $url - the URL for processing the asynchronous request,
use Illuminate\Contracts\Database\Eloquent\Builder; use MoonShine\Laravel\Fields\Relationships\BelongsTo; BelongsTo::make('Country', 'country', resource: CategoryResource::class) ->asyncSearch( 'title', searchQuery: function (Builder $query, Request $request, Field $field) { return $query->where('id', '!=', 2); }, formatted: function ($country, Field $field) { return $country->id . ' | ' . $country->title; }, limit: 10, url: 'https://moonshine-laravel.com/async' )
use Illuminate\Contracts\Database\Eloquent\Builder;
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
 
BelongsTo::make('Country', 'country', resource: CategoryResource::class)
->asyncSearch(
'title',
searchQuery: function (Builder $query, Request $request, Field $field) {
return $query->where('id', '!=', 2);
},
formatted: function ($country, Field $field) {
return $country->id . ' | ' . $country->title;
},
limit: 10,
url: 'https://moonshine-laravel.com/async'
)

When building the query in asyncSearchQuery(), you can use the current values of the form. To do this, it is necessary to pass Request into the callback function.

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

When building the query in asyncSearchQuery(), the initial state of the builder is preserved. If you need to replace it with your builder, use the replaceQuery flag.

use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Http\Request; use MoonShine\Laravel\Fields\Relationships\BelongsTo; use MoonShine\UI\Fields\Select; Select::make('Country', 'country_id'), BelongsTo::make('City', 'city', resource: CityResource::class) ->asyncSearch( 'title', asyncSearchQuery: function (Builder $query, Request $request, Field $field): Builder { return $query->where('country_id', $request->get('country_id')); }, replaceQuery: true )
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
use MoonShine\UI\Fields\Select;
 
Select::make('Country', 'country_id'),
BelongsTo::make('City', 'city', resource: CityResource::class)
->asyncSearch(
'title',
asyncSearchQuery: function (Builder $query, Request $request, Field $field): Builder {
return $query->where('country_id', $request->get('country_id'));
},
replaceQuery: true
)

Associated Fields

To establish a relationship of selection 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 - a callback function for filtering values.
BelongsTo::make('City', 'city', resource: CityResource::class) ->associatedWith('country_id')
BelongsTo::make('City', 'city', 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 - the field with the image,
  • $disk - the file system disk,
  • $dir - the directory relative to the root of the disk.
BelongsTo::make('Country', resource: CountryResource::class) ->withImage('thumb', 'public', 'countries')
BelongsTo::make('Country', resource: CountryResource::class)
->withImage('thumb', 'public', 'countries')

belongs_to_image

belongs_to_image_dark

Options

All selection options are available for modification via data attributes:

BelongsTo::make('Country', resource: CountryResource::class) ->searchable() ->customAttributes([ 'data-search-result-limit' => 5 ])
BelongsTo::make('Country', resource: CountryResource::class)
->searchable()
->customAttributes([
'data-search-result-limit' => 5
])

For more detailed information, please refer to Choices.

Native Mode

The native() method disables the Choices.js library and displays the selection in native mode.

BelongsTo::make('Type')->native()
BelongsTo::make('Type')->native()

Reactivity

This field supports reactivity.

By default, BelongsTo links to the edit page, using the link method under the hood. If needed, you can override the link:

BelongsTo::make( __('moonshine::ui.resource.role'), 'moonshineUserRole', resource: MoonShineUserRoleResource::class, ) ->link( link: fn(string $value, BelongsTo $ctx) => $ctx->getResource()->getDetailPageUrl($ctx->getData()->getKey()), name: fn(string $value) => $value, icon: 'users', blank: true, )
BelongsTo::make(
__('moonshine::ui.resource.role'),
'moonshineUserRole',
resource: MoonShineUserRoleResource::class,
)
->link(
link: fn(string $value, BelongsTo $ctx) => $ctx->getResource()->getDetailPageUrl($ctx->getData()->getKey()),
name: fn(string $value) => $value,
icon: 'users',
blank: true,
)