Basics
You're browsing the documentation for an old version of MoonShine. Consider upgrading your project to MoonShine 2.x.
-
Sections
Fields is one of the most important sections along with resources. We have already discussed the process of Fields registration in the Resource section, but let's figure out how to customize them to your needs! The fluent interface is used for convenience
# Make
First of all, let's understand how the make
method works when creating an instance of a field
Text::make(string $label = null, string $field = null, ResourceContract|string|null $resource = null)
$label - Label, field header
$field - A field in the database (e.g. name) or a relation (e.g. countries)
$resource - If $field is a relation, then in this parameter you need to specify a field
in the linked table that will be displayed in the view
$resource can also be a Resource class. In this case, if the
$titleField
property is specified, the field of the relation will be defined through it
//...class MoonShineUserResource extends Resource{public static string $model = MoonshineUser::class; public static string $title = 'Administrators'; public string $titleField = 'name'; //...
# Displaying
The fields are displayed at the page (the main page of the resource) and at the create/edit page.
To exclude the field from the main page or the page with the form, you can use
hideOnIndex/hideOnForm/hideOnDetail
methods and showOnIndex/showOnForm/showOnDetail
reverse methods.
To exclude it from the edit or add page only -
use hideOnCreate/hideOnUpdate/showOnCreate/showOnUpdate
//... public function fields(): array{ return [ Block::make('Block title', [ ID::make(), Text::make('Title', 'title') ->hideOnIndex() ->hideOnForm() , ]) ];} //...
# Conditional display
This method also accepts bool, or Closure
//... public function fields(): array{ return [ Block::make('Block title', [ ID::make(), Text::make('Title', 'title') ->hideOnIndex(auth()->check()) , ]) ];} //...
# Attributes
As the form renders the html element, you can use basic html attributes as well.
Such as disabled
, autocomplete
, readonly
, multiple
etc.
//... public function fields(): array{ return [ Block::make('Block title', [ Text::make('Title', 'title') ->disabled() ->hidden() ->readonly(), ]; ]) } //...
# Arbitrary attributes
//... public function fields(): array{ return [ Block::make('Block title', [ Password::make('Password', 'password') ->customAttributes(['autocomplete' => 'off']) ]) ];} //...
# Required field
To make the field mandatory, you must use the required
method
//... public function fields(): array{ return [ Block::make('Block title', [ Text::make('Title', 'title') ->required() ]) ];} //...
# Dynamic value
//... public function fields(): array{ return [ Block::make('Block title', [ Text::make('Name', 'first_name', fn($item) => $item->first_name . ' ' . $item->last_name) // Example if you want to separate the logic for the main and for editing Text::make('Price', resource: function ($item) { if(request()->routeIs('*.index')) { return $item->price; } return $item->exists ? $item->price->raw() : 0; }), ]) ];} //...
# Hint
You can add a hint with a description to the field by calling the hint
//... public function fields(): array{ return [ Number::make('Rating') ->hint('From 0 to 5') ->min(0) ->max(5) ->stars() ];} //...
# Link
You can add a link to the field (e.g. with instructions)
addLink(string $name, string $link, bool $blank = false)
//... public function fields(): array{ return [ Text::make('Title', 'title') ->addLink('YouTube', 'https://youtube.com') // or with the anonymous function ->addLink('Test', function() { if(!$this->getItem()) { return route('admin.brands.index'); } return route('admin.brands.edit', $this->getItem()->brand_id); }), ];} //...
# Nullable
If you want to save NULL nullable()
by default
# Sorting
To be able to sort the field on the main page of the resource, you must add the sortable
method
//... public function fields(): array{ return [ Text::make('Title', 'title') ->sortable() ];} //...
# Hide label
The fieldContainer
method hides Label fields to save space,
especially useful in conjunction with the Flex
decoration
//... public function fields(): array{ return [ Text::make('Title', 'title') ->fieldContainer(false) ];} //...
# Default value
Use the default
method if you want to specify a default value for the field
//... public function fields(): array{ return [ Text::make('Title', 'title') ->default('-') ];} //...
# Display condition
There may be a need to display a field only if the value of another field
in the form has a certain value (For example: display the phone only if there is a check mark for it).
For these purposes, the showWhen($column, $operator, $value)
method is used
Available operators:
= < > <= >= != in not in
If the operator is not specified, then =
will be used
//... public function fields(): array{ return [ Phone::make('Phone', 'phone') ->showWhen('has_phone','=', 1) // или Phone::make('Phone', 'phone') ->showWhen('has_phone', 1) ];} //...
If the statement is in
or not in
,
then in $value
you need to pass an array
//... public function fields(): array{ return [ Select::make('List', 'list')->multiple()->options([ 'value 1' => 'Option Label 1', 'value 2' => 'Option Label 2', 'value 3' => 'Option Label 3', ]), Text::make('Name', 'name') ->showWhen('list', 'not in', ['value 1', 'value 3']), Textarea::make('Content', 'content') ->showWhen('list', 'in', ['value 2', 'value 3']) ];} //...
# Ability to save
//... public function fields(): array{ return [ Text::make('Title', 'title') ->canSave(false) // or ->canSave(fn() => false) ];} //...
# Events
When writing your own Fields, you may need to interact with events before and after saving. To do this, you have to implement the relevant methods in your custom field
public function beforeSave(Model $item): void{ //} public function afterSave(Model $item): void{ //}
# Change view
Sometimes it makes sense to change the view using a fluent interface (For example, if you use filters or fields outside of MoonShine)
Text::make('Title') ->customView('fields.my-custom-input'),
# Methods by condition
The when
method implements the fluent interface
and will execute a callback when the first argument, passed to the method is true.
Text::make('Slug') ->when(isset($this->getItem()->id), fn(Text $field) => $field->locked()),
The field instance will be passed to the callback function.
The second callback can be passed to the when
method, it will be executed,
when the first argument passed to the method has a false value.
Text::make('Slug') ->when( isset($this->getItem()->id), fn(Text $field) => $field->locked(), fn(Text $field) => $field->hidden() ),
The unless
method is the reverse of the when
method and will execute the first callback,
when the first argument has a false value, otherwise the second callback will be executed if it was passed to the method.
Text::make('Slug') ->unless( auth('moonshine')->user()->moonshine_user_role_id === 1, fn(Text $field) => $field->readonly()->hideOnCreate(), fn(Text $field) => $field->locked() ),