Основы
Вы просматриваете документацию старой версии MoonShine. Рассмотрите возможность обновления вашего проекта до MoonShine 2.x.
-
Разделы
Поля один из важнейших разделов вместе с ресурсами. В разделе ресурсы мы уже рассмотрели как регистрировать поля, а сейчас разберемся как их настраивать под свои нужды! Для удобства используется fluent интерфейс
# Make
Для начала разберемся в методе make
при создании экземпляра поля
Text::make(string $label = null, string $field = null, ResourceContract|string|null $resource = null)
$label - Лейбл, заголовок поля
$field - Поле в базе (например name) или отношение (например countries)
$resource - В случае если $field - отношение, то в этом параметре необходимо указать поле
в связанной таблице, которое будет отображаться во view
$resource также может быть Resource классом в котором если будет указано свойство
$titleField
, то поле у отношения будет определено через него
//...class MoonShineUserResource extends Resource{public static string $model = MoonshineUser::class; public static string $title = 'Администраторы'; public string $titleField = 'name'; //...
# Отображение
Поля отображаются на странице со списком (главная страница ресурса) и страница создания/редактирования.
Чтобы исключить вывод поля на главной либо на странице с формой, можно воспользоваться методами
hideOnIndex/hideOnForm/hideOnDetail
, обратные методы showOnIndex/showOnForm/showOnDetail
.
Чтобы исключить только со страницы редактирования или добавления -
hideOnCreate/hideOnUpdate/showOnCreate/showOnUpdate
//... public function fields(): array{ return [ Block::make('Block title', [ ID::make(), Text::make('Заголовок', 'title') ->hideOnIndex() ->hideOnForm() , ]) ];} //...
# Отображение с условием
Метод также принимает bool, либо Closure
//... public function fields(): array{ return [ Block::make('Block title', [ ID::make(), Text::make('Заголовок', 'title') ->hideOnIndex(auth()->check()) , ]) ];} //...
# Аттрибуты
Так как на форме рендерится html элемент, то также есть возможность управлять базовыми html аттрибутами.
Такими как disabled
, autocomplete
, readonly
, multiple
и тд.
//... public function fields(): array{ return [ Block::make('Block title', [ Text::make('Заголовок', 'title') ->disabled() ->hidden() ->readonly(), ]; ]) } //...
# Произвольные аттрибуты
//... public function fields(): array{ return [ Block::make('Block title', [ Password::make('Пароль', 'password') ->customAttributes(['autocomplete' => 'off']) ]) ];} //...
# Обязательное поле
Чтобы сделать поле обязательным к заполнению, необходимо воспользоваться методом required
//... public function fields(): array{ return [ Block::make('Block title', [ Text::make('Заголовок', 'title') ->required() ]) ];} //...
# Динамическое значение
//... public function fields(): array{ return [ Block::make('Block title', [ Text::make('Имя', 'first_name', fn($item) => $item->first_name . ' ' . $item->last_name) // Пример если нужно разделить логику для главной и для редактирования Text::make('Price', resource: function ($item) { if(request()->routeIs('*.index')) { return $item->price; } return $item->exists ? $item->price->raw() : 0; }), ]) ];} //...
# Подсказка
Полю можно добавить подсказку с описанием вызвав метод hint
//... public function fields(): array{ return [ Number::make('Rating') ->hint('From 0 to 5') ->min(0) ->max(5) ->stars() ];} //...
# Ссылка
Полю можно добавить ссылку (например с инструкциями)
addLink(string $name, string $link, bool $blank = false)
//... public function fields(): array{ return [ Text::make('Link') ->addLink('CutCode', 'https://cutcode.dev', true) // или с анонимной функцией ->addLink('Test', function() { if(!$this->getItem()) { return route('admin.brands.index'); } return route('admin.brands.edit', $this->getItem()->brand_id); }), ];} //...
# Nullable
Если необходимо по умолчанию сохранять NULL nullable()
# Сортировка
Для возможности сортировки поля на главной странице ресурса необходимо добавить метод sortable
//... public function fields(): array{ return [ Text::make('Заголовок', 'title') ->sortable() ];} //...
# Скрыть label
Метод fieldContainer
скроет Label поля для экономии места, особенно удобно
использовать совместно с декорацией Flex
//... public function fields(): array{ return [ Text::make('Заголовок', 'title') ->fieldContainer(false) ];} //...
# Значение по умолчанию
Метод default
если необходимо указать значение по умолчанию для поля
//... public function fields(): array{ return [ Text::make('Заголовок', 'title') ->default('-') ];} //...
# Условие отображения
Может возникнуть потребность отображать поле только в том случае, если значение у другого поля
в форме имеет определенное значение (Например: отображать телефон, только если стоит галочка, что телефон есть).
Для этих целей используется метод showWhen($column, $operator, $value)
Доступные операторы:
= < > <= >= != in not in
Если оператор не указан, то будет использоваться =
//... public function fields(): array{ return [ Phone::make('Phone', 'phone') ->showWhen('has_phone','=', 1) // или Phone::make('Phone', 'phone') ->showWhen('has_phone', 1) ];} //...
Если оператор имеет значение in
или not in
,
то в $value
необходимо передать массив
//... 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']) ];} //...
# Возможность сохранения
//... public function fields(): array{ return [ Text::make('Заголовок', 'title') ->canSave(false) // или ->canSave(fn() => false) ];} //...
# События
При написании собственных Fields может возникнуть потребность взаимодействовать с событиями до и после сохранения, для этого в вашем кастомном поле необходимо реализовать соответствующие методы
public function beforeSave(Model $item): void{ //} public function afterSave(Model $item): void{ //}
# Смена view
Иногда имеет смысл изменить view с помощью fluent interface (Как пример если используете фильтры или поля вне MoonShine)
Text::make('Title') ->customView('fields.my-custom-input'),
# Методы по условию
Метод when
реализует fluent interface
и выполнит callback, когда первый аргумент, переданный методу, имеет значение true.
Text::make('Slug') ->when(isset($this->getItem()->id), fn(Text $field) => $field->locked()),
Экземпляр поля, будет передан в функции callback.
Методу when
может быть передан второй callback, он будет выполнен,
когда первый аргумент, переданный методу, имеет значение false.
Text::make('Slug') ->when( isset($this->getItem()->id), fn(Text $field) => $field->locked(), fn(Text $field) => $field->hidden() ),
Метод unless
обратный методу when
и выполнит первый callback,
когда первый аргумент имеет значение false, иначе будет выполнен второй callback, если он передан методу.
Text::make('Slug') ->unless( auth('moonshine')->user()->moonshine_user_role_id === 1, fn(Text $field) => $field->readonly()->hideOnCreate(), fn(Text $field) => $field->locked() ),