- Основы
- Открытие в новом окне
- Иконка
- Цвет
- Бейдж
- onClick
- Модальное окно
- Подтверждение
- Offcanvas
- Группировка
- Массовые действия
- Асинхронный режим
- Отправка событий
- Наполнение данными
Основы
Когда вам нужно добавить кнопку с определенным действием, на помощь приходят ActionButton
.
В MoonShine они уже используются - в формах, таблицах, на страницах.
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract; make( Closure|string $label, Closure|string $url = '#', ?DataWrapperContract $data = null,)
label
- текст кнопки,url
- URL ссылки кнопки,data
- опциональные данные кнопки, доступные в замыканиях.
use MoonShine\UI\Components\ActionButton; ActionButton::make( 'Button Label', 'https://moonshine-laravel.com')
Открытие в новом окне
Метод blank()
позволяет открыть URL в новом окне. Добавится атрибут target="_blank"
.
ActionButton::make('Button Label', '/') ->blank()
Иконка
Метод icon()
позволяет указать иконку для кнопки.
ActionButton::make('Button Label') ->icon('pencil')
Для получения более подробной информации обратитесь к разделу Иконки.
Цвет
Для ActionButton
есть набор методов, которые позволяют установить цвет кнопки:
primary()
, secondary()
, warning()
, success()
и error()
.
ActionButton::make('Button Label') ->primary()
Бейдж
Метод badge()
позволяет добавить бейдж к кнопке.
badge(Closure|string|int|float|null $value)
ActionButton::make('Button Label') ->badge(fn() => Comment::count())
onClick
Метод onClick()
позволяет выполнить js-код при клике.
ActionButton::make('Button Label') ->onClick(fn() => "alert('Пример')", 'prevent')
Если вам необходимо получить данные в методе onClick()
, то воспользуйтесь методом onAfterSet()
.
ActionButton::make('Alert') ->onAfterSet(function (?DataWrapperContract $data, ActionButton $button) { return $button->onClick(fn() => 'alert('.$data?->getKey().')'); })
Модальное окно
Основы
Для вызова модального окна при нажатии на кнопку используйте метод inModal()
.
use MoonShine\Contracts\UI\ActionButtonContract;use MoonShine\UI\Components\Modal; /** * @param ?Closure(Modal $modal, ActionButtonContract $ctx): Modal $builder */inModal( Closure|string|null $title = null, Closure|string|null $content = null, Closure|string|null $name = null, ?Closure $builder = null,)
title
- заголовок модального окна,content
- содержимое модального окна,name
- уникальное наименование модального окна для вызова событий,builder
- замыкание с доступом к компонентуModal
.
Для получения более подробной информации по методам модальных окон, обратитесь к разделу Modal.
use MoonShine\UI\Components\ActionButton;use MoonShine\UI\Components\Modal; ActionButton::make('Button Label') ->inModal( title: 'Modal Window Title', content: 'Modal Window Content', name: 'my-modal', builder: fn(Modal $modal, ActionButton $ctx) => $modal )
Если вы используете несколько однотипных модальных окон, например в таблицах для каждого элемента, то вам необходимо указывать уникальный name
для каждой.
use MoonShine\Contracts\UI\ActionButtonContract;use MoonShine\UI\Components\ActionButton; ActionButton::make('Button Label') ->inModal( name: static fn (mixed $item, ActionButtonContract $ctx): string => "delete-button-{$ctx->getData()?->getKey()}" )
Вы также можете открыть модальное окно с помощью метода toggleModal()
, а если ActionButton
находится внутри модального окна, то просто openModal()
.
use MoonShine\UI\Components\ActionButton;use MoonShine\UI\Components\Modal; Modal::make('Title','Content') ->name('my-modal'), ActionButton::make('Open modal window') ->toggleModal('my-modal'),
Асинхронный режим
Если вам нужно загрузить содержимое в модальное окно асинхронно, то включите асинхронный режим с помощью метода async()
у ActionButton
.
ActionButton::make( 'Button Label', to_page('action_button', fragment: 'doc-content'),) ->async() ->inModal( title: fn() => 'Modal Window Title', )
О Fragment можно узнать в разделе "Компоненты".
Подтверждение
Метод withConfirm()
позволяет создать кнопку с подтверждением действия.
/** * @param ?Closure(FormBuilderContract $form, mixed $data): FormBuilderContract $formBuilder * @param ?Closure(Modal $modal, ActionButtonContract $ctx): Modal $modalBuilder */withConfirm( Closure|string|null $title = null, Closure|string|null $content = null, Closure|string|null $button = null, Closure|array|null $fields = null, HttpMethod $method = HttpMethod::POST, ?Closure $formBuilder = null, ?Closure $modalBuilder = null, Closure|string|null $name = null,)
ActionButton::make('Button Label') ->withConfirm( title: 'Confirmation Modal Window Title', content: 'Confirmation Modal Window Content', button: 'Confirmation Modal Window Button', // опционально - дополнительные поля формы fields: null, method: HttpMethod::POST, // опционально - замыкание с FormBuilder formBuilder: null, // опционально - замыкание с Modal modalBuilder: null, name: 'my-modal', )
Если вы используете несколько однотипных модальных окон, например в таблицах для каждого элемента, то вам необходимо указывать уникальный name
для каждой.
ActionButton::make('Button Label') ->inModal( name: static fn (mixed $item, ActionButtonContract $ctx): string => "delete-button-{$ctx->getData()?->getKey()}" )
Offcanvas
Для того чтобы при нажатии на кнопку вызывалась боковая панель (Offcanvas), используйте метод inOffCanvas()
.
use MoonShine\UI\Components\ActionButton;use MoonShine\UI\Components\OffCanvas; ActionButton::make('Button Label') ->inOffCanvas( title: fn() => 'Offcanvas Title', content: fn() => 'Content', name: false, builder: fn(OffCanvas $offCanvas, ActionButton $ctx) => $offCanvas->left(), // опционально - необходимо чтобы компоненты были доступны для поиска в системе, т.к. content всего лишь HTML components: [], )
Группировка
Если вам необходимо организовать логику с несколькими ActionButton
, при этом некоторые из них должны быть скрыты или отображены в выпадающем меню, используйте компонент ActionGroup
.
use MoonShine\UI\Components\ActionButton;use MoonShine\UI\Components\ActionGroup; ActionGroup::make([ ActionButton::make('Button 1', '/') ->canSee(fn() => false), ActionButton::make('Button 2', '/', $model) ->canSee(fn($model) => $model->active)])
Подробнее о компоненте ActionGroup.
Отображение
Благодаря ActionGroup
вы также можете изменить отображение кнопок, отображать их в линию или в выпадающем меню для экономии места.
use MoonShine\UI\Components\ActionButton;use MoonShine\UI\Components\ActionGroup; ActionGroup::make([ ActionButton::make('Button 1', '/') ->showInLine(), ActionButton::make('Button 2', '/') ->showInDropdown()])
Массовые действия
Метод bulk()
позволяет создать кнопку массового действия для ModelResource
.
protected function indexButtons(): ListOf{ return parent::indexButtons() ->add(ActionButton::make('Link', '/endpoint')->bulk());}
Метод bulk()
, используется только внутри ModelResource
.
Асинхронный режим
Метод async()
позволяет реализовать асинхронную работу для ActionButton
.
use MoonShine\Support\DTOs\AsyncCallback;use MoonShine\Support\Enums\HttpMethod; async( HttpMethod $method = HttpMethod::GET, ?string $selector = null, array $events = [], ?AsyncCallback $callback = null,)
$method
- метод асинхронного запроса,$selector
- селектор элемента, содержимое которого изменится в соответствии с ответом,$events
- события, которые будут вызваны после успешного запроса,$callback
- js функция обратного вызова после получения ответа.
ActionButton::make('Button Label', '/endpoint') ->async()
Уведомления
Если вам нужно отобразить уведомление или сделать редирект после клика, то достаточно реализовать json ответ согласно следующей структуре:
{ "message": "Toast", "messageType": "success", "redirect": "/url"}
Параметр redirect
является необязательным.
HTML содержимое
Если вам нужно заменить область HTML по клику, то можно вернуть HTML содержимое или json с ключом html в ответе, например:
{"html": "Html content"}
ActionButton::make('Button Label', '/endpoint') ->async(selector: '#my-selector')
События
После успешного запроса вы можете вызвать события.
ActionButton::make('Button Label', '/endpoint') ->async( events: [ AlpineJs::event(JsEvent::TABLE_UPDATED, $this->getListComponentName()) ] )
Для работы события JsEvent::TABLE_UPDATED
у таблицы должен быть включен асинхронный режим.
Обратный вызов
Если вам нужно обработать ответ иным способом, необходимо реализовать функцию-обработчик и указать её в методе async()
.
ActionButton::make('Button Label', '/endpoint') ->async( callback: AsyncCallback::with(responseHandler: 'myFunction') )
document.addEventListener("moonshine:init", () => { MoonShine.onCallback('myFunction', function(response, element, events, component) { if(response.confirmed === true) { component.$dispatch('toast', {type: 'success', text: 'Success'}) } else { component.$dispatch('toast', {type: 'error', text: 'Error'}) } })})
Подробности в разделе Js.
Вызов методов
method()
позволяет указать имя метода в ресурсе и вызвать его асинхронно при нажатии на ActionButton
без необходимости создания дополнительных контроллеров.
method( string $method, array|Closure $params = [], ?string $message = null, ?string $selector = null, array $events = [], ?AsyncCallback $callback = null, ?PageContract $page = null, ?ResourceContract $resource = null,)
$method
- имя метода,$params
- опционально - параметры для запроса,$message
- опционально - сообщение при успешном выполнении,$selector
- опционально - селектор элемента, содержимое которого изменится,$events
- опционально - события, которые будут вызваны после успешного запроса,$callback
- опционально - js функция обратного вызова после получения ответа,$page
- опционально - страница, содержащая метод (если кнопка находится вне страницы и ресурса),$resource
- опционально - ресурс, содержащий метод (если кнопка находится вне ресурса).
ActionButton::make('Button Label') ->method('updateSomething')
// С уведомлениемpublic function updateSomething(MoonShineRequest $request): MoonShineJsonResponse{ // $request->getResource(); // $request->getResource()->getItem(); // $request->getPage(); return MoonShineJsonResponse::make()->toast('My message', ToastType::SUCCESS);} // Редиректpublic function updateSomething(MoonShineRequest $request): MoonShineJsonResponse{ return MoonShineJsonResponse::make()->redirect('/');} // Редиректpublic function updateSomething(MoonShineRequest $request): RedirectResponse{ return back();} // Исключениеpublic function updateSomething(MoonShineRequest $request): void{ throw new \Exception('My message');} // Пользовательский JSON-ответpublic function updateSomething(MoonShineRequest $request){ return MoonShineJsonResponse::make()->html('Content');}
Методы, вызываемые через ActionButton
в ресурсе, должны быть публичными!
Для доступа к данным из запроса вы должны передать их в параметрах.
Передача текущего элемента
Если в запросе присутствует resourceItem
, вы можете получить доступ к текущему элементу в ресурсе через метод getItem()
.
Когда в данных есть модель, и кнопка создается в методе indexButtons()
или detailButtons()
или formButtons()
TableBuilder, CardsBuilder или FormBuilder,
она автоматически заполняется данными, и параметры будут содержать resourceItem
.
Когда кнопка находится на странице формы ModelResource
, вы можете передать id текущего элемента.
ActionButton::make('Button Label') ->method( 'updateSomething', params: ['resourceItem' => $this->getResource()->getItemID()] )
Когда кнопка находится в индексной таблице ModelResource
, нужно использовать замыкание.
ActionButton::make('Button Label') ->method( 'updateSomething', params: fn(Model $item) => ['resourceItem' => $item->getKey()] )
Значения полей
Метод withSelectorsParams()
позволяет передавать значения полей с запросом, используя селекторы элементов.
ActionButton::make('Button Label') ->method('updateSomething') ->withSelectorsParams([ 'alias' => '[data-column="title"]', 'slug' => '#slug', ])
use MoonShine\Laravel\Http\Responses\MoonShineJsonResponse;use MoonShine\Laravel\MoonShineRequest; public function updateSomething(MoonShineRequest $request): MoonShineJsonResponse{ return MoonShineJsonResponse::make() ->toast($request->get('slug', 'Error'));}
При использовании метода withSelectorsParams()
запросы будут отправляться через POST
.
Скачивание
Вызываемый метод может возвращать BinaryFileResponse
, что позволяет скачать файл.
ActionButton::make('Download') ->method('download')
use Symfony\Component\HttpFoundation\BinaryFileResponse; public function download(): BinaryFileResponse{ // ... return response()->download($file);}
Отправка событий
Для отправки javascript-событий вы можете использовать метод dispatchEvent()
.
dispatchEvent(array|string $events)
ActionButton::make('Refresh') ->dispatchEvent( AlpineJs::event(JsEvent::TABLE_UPDATED, 'index-table') )
По умолчанию при вызове события с запросом будут отправлены все query параметры (например, ?param=value
) из url
(указанного при создании ActionButton
).
Исключить ненужные можно через параметр exclude
.
ActionButton::make('Refresh') ->dispatchEvent( AlpineJs::event(JsEvent::TABLE_UPDATED, 'index-table'), exclude: ['something'], )
Также можно полностью исключить отправку withoutPayload
.
ActionButton::make('Refresh') ->dispatchEvent( AlpineJs::event(JsEvent::TABLE_UPDATED, 'index-table'), withoutPayload: true )
Параметры запроса URL
Вы можете включить параметры текущего запроса URL (например, ?param=value
) в запрос.
ActionButton::make('Button Label') ->withQueryParams()
Наполнение данными
При работе с ModelResource
, кнопки действий ActionButton
обычно автоматически наполняются необходимыми данными.
Этот процесс происходит "под капотом" с использованием метода setData()
.
Давайте рассмотрим этот механизм подробнее.
ActionButton::make('Button Label') ->setData(?DataWrapperContract $data = null)
Подробнее о DataWrapperContract
читайте в разделе TypeCasts.
Также доступны методы с колбеками до и после наполнения кнопки.
ActionButton::make('Button Label') ->onBeforeSet(fn(?DataWrapperContract $data, ActionButton $ctx) => $data)
ActionButton::make('Button Label') ->onAfterSet(function(?DataWrapperContract $data, ActionButton $ctx): void { // logic })