ModelResource
extends CrudResource
and provides functionality for working with Eloquent models.
It serves as a foundation for creating resources associated with database models.
ModelResource
offers methods for performing CRUD operations, managing relationships, applying filters, and much more.
You can also refer to the section on CrudResource.
CrudResource
is an abstract class providing a basic interface for CRUD
operations without binding to a storage and data type.
Under the hood, ModelResource
extends CrudResource
and immediately includes the capability to work with Eloquent
.
If you delve into the details of MoonShine, you will see all the standard Controller
, Model
, and blade views
.
If you were developing independently, you could create resource controllers and resource routes as follows:
php artisan make:controller Controller --resource
php artisan make:controller Controller --resource
php artisan make:controller Controller --resource
php artisan make:controller Controller --resource
php artisan make:controller Controller --resource
use Illuminate\Support\Facades\Route;
Route::resource('resources', Controller::class);
namespaces
use Illuminate\Support\Facades\Route;
Route::resource('resources', Controller::class);
use Illuminate\Support\Facades\Route;
Route::resource('resources', Controller::class);
namespaces
use Illuminate\Support\Facades\Route;
Route::resource('resources', Controller::class);
use Illuminate\Support\Facades\Route;
Route::resource('resources', Controller::class);
But this work can be entrusted to the admin panel MoonShine, which will generate and declare them automatically.
ModelResource
is the primary component for creating a section in the admin panel when working with databases.
php artisan moonshine:resource Post
php artisan moonshine:resource Post
php artisan moonshine:resource Post
php artisan moonshine:resource Post
php artisan moonshine:resource Post
For more details, refer to the Commands.
Basic parameters that can be changed for a resource to customize its functionality.
namespace App\MoonShine\Resources;
use App\Models\Post;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected string $model = Post::class;
protected string $title = 'Posts';
protected array $with = ['category'];
protected string $column = 'id';
}
namespaces
namespace App\MoonShine\Resources;
use App\Models\Post;
use MoonShine\Laravel\Resources\ModelResource;
/**
* @extends ModelResource<Post>
*/
class PostResource extends ModelResource
{
// Model
protected string $model = Post::class;
// Section title
protected string $title = 'Posts';
// Eager load
protected array $with = ['category'];
// Field for displaying values in relationships and breadcrumbs
protected string $column = 'id';
// ...
}
namespace App\MoonShine\Resources;
use App\Models\Post;
use MoonShine\Laravel\Resources\ModelResource;
/**
* @extends ModelResource<Post>
*/
class PostResource extends ModelResource
{
// Model
protected string $model = Post::class;
// Section title
protected string $title = 'Posts';
// Eager load
protected array $with = ['category'];
// Field for displaying values in relationships and breadcrumbs
protected string $column = 'id';
// ...
}
namespaces
namespace App\MoonShine\Resources;
use App\Models\Post;
use MoonShine\Laravel\Resources\ModelResource;
/**
* @extends ModelResource<Post>
*/
class PostResource extends ModelResource
{
// Model
protected string $model = Post::class;
// Section title
protected string $title = 'Posts';
// Eager load
protected array $with = ['category'];
// Field for displaying values in relationships and breadcrumbs
protected string $column = 'id';
// ...
}
namespace App\MoonShine\Resources;
use App\Models\Post;
use MoonShine\Laravel\Resources\ModelResource;
/**
* @extends ModelResource<Post>
*/
class PostResource extends ModelResource
{
// Model
protected string $model = Post::class;
// Section title
protected string $title = 'Posts';
// Eager load
protected array $with = ['category'];
// Field for displaying values in relationships and breadcrumbs
protected string $column = 'id';
// ...
}

The resource is automatically registered in MoonShineServiceProvider
when executing the command php artisan moonshine:resource
.
However, if you create a section manually, you need to declare it in the system within MoonShineServiceProvider
.
namespace App\Providers;
use App\MoonShine\Resources\ArticleResource;
use Illuminate\Support\ServiceProvider;
use MoonShine\Contracts\Core\DependencyInjection\CoreContract;
use MoonShine\Laravel\DependencyInjection\ConfiguratorContract;
use MoonShine\Laravel\DependencyInjection\MoonShine;
use MoonShine\Laravel\DependencyInjection\MoonShineConfigurator;
class MoonShineServiceProvider extends ServiceProvider
{
public function boot(
CoreContract $core,
ConfiguratorContract $config,
): void
{
$core
->resources([
MoonShineUserResource::class,
MoonShineUserRoleResource::class,
ArticleResource::class,
])
->pages([
...$config->getPages(),
])
;
}
}
namespaces
namespace App\Providers;
use App\MoonShine\Resources\ArticleResource;
use Illuminate\Support\ServiceProvider;
use MoonShine\Contracts\Core\DependencyInjection\CoreContract;
use MoonShine\Laravel\DependencyInjection\ConfiguratorContract;
use MoonShine\Laravel\DependencyInjection\MoonShine;
use MoonShine\Laravel\DependencyInjection\MoonShineConfigurator;
class MoonShineServiceProvider extends ServiceProvider
{
/**
* @param MoonShine $core
* @param MoonShineConfigurator $config
*
*/
public function boot(
CoreContract $core,
ConfiguratorContract $config,
): void
{
$core
->resources([
MoonShineUserResource::class,
MoonShineUserRoleResource::class,
ArticleResource::class,
// ...
])
->pages([
...$config->getPages(),
])
;
}
}
namespace App\Providers;
use App\MoonShine\Resources\ArticleResource;
use Illuminate\Support\ServiceProvider;
use MoonShine\Contracts\Core\DependencyInjection\CoreContract;
use MoonShine\Laravel\DependencyInjection\ConfiguratorContract;
use MoonShine\Laravel\DependencyInjection\MoonShine;
use MoonShine\Laravel\DependencyInjection\MoonShineConfigurator;
class MoonShineServiceProvider extends ServiceProvider
{
/**
* @param MoonShine $core
* @param MoonShineConfigurator $config
*
*/
public function boot(
CoreContract $core,
ConfiguratorContract $config,
): void
{
$core
->resources([
MoonShineUserResource::class,
MoonShineUserRoleResource::class,
ArticleResource::class,
// ...
])
->pages([
...$config->getPages(),
])
;
}
}
namespaces
namespace App\Providers;
use App\MoonShine\Resources\ArticleResource;
use Illuminate\Support\ServiceProvider;
use MoonShine\Contracts\Core\DependencyInjection\CoreContract;
use MoonShine\Laravel\DependencyInjection\ConfiguratorContract;
use MoonShine\Laravel\DependencyInjection\MoonShine;
use MoonShine\Laravel\DependencyInjection\MoonShineConfigurator;
class MoonShineServiceProvider extends ServiceProvider
{
/**
* @param MoonShine $core
* @param MoonShineConfigurator $config
*
*/
public function boot(
CoreContract $core,
ConfiguratorContract $config,
): void
{
$core
->resources([
MoonShineUserResource::class,
MoonShineUserRoleResource::class,
ArticleResource::class,
// ...
])
->pages([
...$config->getPages(),
])
;
}
}
namespace App\Providers;
use App\MoonShine\Resources\ArticleResource;
use Illuminate\Support\ServiceProvider;
use MoonShine\Contracts\Core\DependencyInjection\CoreContract;
use MoonShine\Laravel\DependencyInjection\ConfiguratorContract;
use MoonShine\Laravel\DependencyInjection\MoonShine;
use MoonShine\Laravel\DependencyInjection\MoonShineConfigurator;
class MoonShineServiceProvider extends ServiceProvider
{
/**
* @param MoonShine $core
* @param MoonShineConfigurator $config
*
*/
public function boot(
CoreContract $core,
ConfiguratorContract $config,
): void
{
$core
->resources([
MoonShineUserResource::class,
MoonShineUserRoleResource::class,
ArticleResource::class,
// ...
])
->pages([
...$config->getPages(),
])
;
}
}
All pages in MoonShine have a Layout
, and each page can have its own.
By default, when MoonShine is installed, a base MoonShineLayout
is added to the directory app/MoonShine/Layouts
.
In Layout
, everything related to the appearance of your pages, including navigation, is customized.
To add a section to the menu, you need to declare it via the menu()
method in Layout
.
namespace App\MoonShine\Layouts;
use App\MoonShine\Resources\PostResource;
use MoonShine\Laravel\Layouts\CompactLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuItem;
final class MoonShineLayout extends CompactLayout
{
protected function menu(): array
{
return [
MenuGroup::make(__('moonshine::ui.resource.system'), [
MenuItem::make(
__('moonshine::ui.resource.admins_title'),
MoonShineUserResource::class
),
MenuItem::make(
__('moonshine::ui.resource.role_title'),
MoonShineUserRoleResource::class
),
]),
MenuItem::make('Posts', PostResource::class),
];
}
}
namespaces
namespace App\MoonShine\Layouts;
use App\MoonShine\Resources\PostResource;
use MoonShine\Laravel\Layouts\CompactLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuItem;
final class MoonShineLayout extends CompactLayout
{
// ...
protected function menu(): array
{
return [
MenuGroup::make(__('moonshine::ui.resource.system'), [
MenuItem::make(
__('moonshine::ui.resource.admins_title'),
MoonShineUserResource::class
),
MenuItem::make(
__('moonshine::ui.resource.role_title'),
MoonShineUserRoleResource::class
),
]),
MenuItem::make('Posts', PostResource::class),
// ...
];
}
}
namespace App\MoonShine\Layouts;
use App\MoonShine\Resources\PostResource;
use MoonShine\Laravel\Layouts\CompactLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuItem;
final class MoonShineLayout extends CompactLayout
{
// ...
protected function menu(): array
{
return [
MenuGroup::make(__('moonshine::ui.resource.system'), [
MenuItem::make(
__('moonshine::ui.resource.admins_title'),
MoonShineUserResource::class
),
MenuItem::make(
__('moonshine::ui.resource.role_title'),
MoonShineUserRoleResource::class
),
]),
MenuItem::make('Posts', PostResource::class),
// ...
];
}
}
namespaces
namespace App\MoonShine\Layouts;
use App\MoonShine\Resources\PostResource;
use MoonShine\Laravel\Layouts\CompactLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuItem;
final class MoonShineLayout extends CompactLayout
{
// ...
protected function menu(): array
{
return [
MenuGroup::make(__('moonshine::ui.resource.system'), [
MenuItem::make(
__('moonshine::ui.resource.admins_title'),
MoonShineUserResource::class
),
MenuItem::make(
__('moonshine::ui.resource.role_title'),
MoonShineUserRoleResource::class
),
]),
MenuItem::make('Posts', PostResource::class),
// ...
];
}
}
namespace App\MoonShine\Layouts;
use App\MoonShine\Resources\PostResource;
use MoonShine\Laravel\Layouts\CompactLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuItem;
final class MoonShineLayout extends CompactLayout
{
// ...
protected function menu(): array
{
return [
MenuGroup::make(__('moonshine::ui.resource.system'), [
MenuItem::make(
__('moonshine::ui.resource.admins_title'),
MoonShineUserResource::class
),
MenuItem::make(
__('moonshine::ui.resource.role_title'),
MoonShineUserRoleResource::class
),
]),
MenuItem::make('Posts', PostResource::class),
// ...
];
}
}
You can learn about advanced Layout
settings in the section Layout.
You can learn about advanced MenuManager
settings in the section Menu.
By default, the alias of the resource used in the url
is generated based on the class name in kebab-case
, for example:
MoonShineUserResource
-> moon-shine-user-resource
.
To change the alias
, you can use the resource property $alias
or the method getAlias()
.
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected ?string $alias = 'custom-alias';
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected ?string $alias = 'custom-alias';
// ...
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected ?string $alias = 'custom-alias';
// ...
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected ?string $alias = 'custom-alias';
// ...
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected ?string $alias = 'custom-alias';
// ...
}
or
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
public function getAlias(): ?string
{
return 'custom-alias';
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
public function getAlias(): ?string
{
return 'custom-alias';
}
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
public function getAlias(): ?string
{
return 'custom-alias';
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
public function getAlias(): ?string
{
return 'custom-alias';
}
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
public function getAlias(): ?string
{
return 'custom-alias';
}
}
If the resourceItem
parameter is present in the url
of the detail or editing page, you can access the current element in the resource using the getItem()
method.
$this->getItem();
$this->getItem();
$this->getItem();
$this->getItem();
$this->getItem();
You can access the model through the getModel()
method.
$this->getModel();
$this->getModel();
$this->getModel();
$this->getModel();
$this->getModel();
You can add, edit, and view records directly on the listing page in a modal window.
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected bool $createInModal = true;
protected bool $editInModal = true;
protected bool $detailInModal = true;
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected bool $createInModal = true;
protected bool $editInModal = true;
protected bool $detailInModal = true;
// ...
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected bool $createInModal = true;
protected bool $editInModal = true;
protected bool $detailInModal = true;
// ...
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected bool $createInModal = true;
protected bool $editInModal = true;
protected bool $detailInModal = true;
// ...
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected bool $createInModal = true;
protected bool $editInModal = true;
protected bool $detailInModal = true;
// ...
}
By default, when creating and editing a record, a redirect to the form page is performed, but this behavior can be controlled.
use MoonShine\Support\Enums\PageType;
protected ?PageType $redirectAfterSave = PageType::FORM;
public function getRedirectAfterSave(): string
{
return '/';
}
public function getRedirectAfterDelete(): string
{
return $this->getIndexPageUrl();
}
namespaces
use MoonShine\Support\Enums\PageType;
// Through a property in the resource
protected ?PageType $redirectAfterSave = PageType::FORM;
// or through methods (redirect after deletion is also available)
public function getRedirectAfterSave(): string
{
return '/';
}
public function getRedirectAfterDelete(): string
{
return $this->getIndexPageUrl();
}
use MoonShine\Support\Enums\PageType;
// Through a property in the resource
protected ?PageType $redirectAfterSave = PageType::FORM;
// or through methods (redirect after deletion is also available)
public function getRedirectAfterSave(): string
{
return '/';
}
public function getRedirectAfterDelete(): string
{
return $this->getIndexPageUrl();
}
namespaces
use MoonShine\Support\Enums\PageType;
// Through a property in the resource
protected ?PageType $redirectAfterSave = PageType::FORM;
// or through methods (redirect after deletion is also available)
public function getRedirectAfterSave(): string
{
return '/';
}
public function getRedirectAfterDelete(): string
{
return $this->getIndexPageUrl();
}
use MoonShine\Support\Enums\PageType;
// Through a property in the resource
protected ?PageType $redirectAfterSave = PageType::FORM;
// or through methods (redirect after deletion is also available)
public function getRedirectAfterSave(): string
{
return '/';
}
public function getRedirectAfterDelete(): string
{
return $this->getIndexPageUrl();
}
Often, it is necessary to create a resource where the ability to delete, add, or edit is excluded.
This is not about authorization, but rather a global exclusion of these sections.
This can be done easily through the activeActions()
method in the resource.
namespace App\MoonShine\Resources;
use MoonShine\Support\ListOf;
use MoonShine\Laravel\Enums\Action;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected function activeActions(): ListOf
{
return parent::activeActions()
->except(Action::VIEW, Action::MASS_DELETE)
;
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Support\ListOf;
use MoonShine\Laravel\Enums\Action;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function activeActions(): ListOf
{
return parent::activeActions()
->except(Action::VIEW, Action::MASS_DELETE)
// ->only(Action::VIEW)
;
}
}
namespace App\MoonShine\Resources;
use MoonShine\Support\ListOf;
use MoonShine\Laravel\Enums\Action;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function activeActions(): ListOf
{
return parent::activeActions()
->except(Action::VIEW, Action::MASS_DELETE)
// ->only(Action::VIEW)
;
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Support\ListOf;
use MoonShine\Laravel\Enums\Action;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function activeActions(): ListOf
{
return parent::activeActions()
->except(Action::VIEW, Action::MASS_DELETE)
// ->only(Action::VIEW)
;
}
}
namespace App\MoonShine\Resources;
use MoonShine\Support\ListOf;
use MoonShine\Laravel\Enums\Action;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function activeActions(): ListOf
{
return parent::activeActions()
->except(Action::VIEW, Action::MASS_DELETE)
// ->only(Action::VIEW)
;
}
}
You can also create a new list, for example:
use MoonShine\Laravel\Enums\Action;
use MoonShine\Support\ListOf;
protected function activeActions(): ListOf
{
return new ListOf(Action::class, [Action::VIEW, Action::UPDATE]);
}
namespaces
use MoonShine\Laravel\Enums\Action;
use MoonShine\Support\ListOf;
protected function activeActions(): ListOf
{
return new ListOf(Action::class, [Action::VIEW, Action::UPDATE]);
}
use MoonShine\Laravel\Enums\Action;
use MoonShine\Support\ListOf;
protected function activeActions(): ListOf
{
return new ListOf(Action::class, [Action::VIEW, Action::UPDATE]);
}
namespaces
use MoonShine\Laravel\Enums\Action;
use MoonShine\Support\ListOf;
protected function activeActions(): ListOf
{
return new ListOf(Action::class, [Action::VIEW, Action::UPDATE]);
}
use MoonShine\Laravel\Enums\Action;
use MoonShine\Support\ListOf;
protected function activeActions(): ListOf
{
return new ListOf(Action::class, [Action::VIEW, Action::UPDATE]);
}
By default, the index page of the resource model contains only a button for creation.
The topButtons()
method allows you to add additional buttons.
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\Support\AlpineJs;
use MoonShine\Support\Enums\JsEvent;
use MoonShine\Support\ListOf;
use MoonShine\UI\Components\ActionButton;
class PostResource extends ModelResource
{
protected function topButtons(): ListOf
{
return parent::topButtons()->add(
ActionButton::make('Refresh', '#')
->dispatchEvent(AlpineJs::event(JsEvent::TABLE_UPDATED, $this->getListComponentName()))
);
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\Support\AlpineJs;
use MoonShine\Support\Enums\JsEvent;
use MoonShine\Support\ListOf;
use MoonShine\UI\Components\ActionButton;
class PostResource extends ModelResource
{
// ...
protected function topButtons(): ListOf
{
return parent::topButtons()->add(
ActionButton::make('Refresh', '#')
->dispatchEvent(AlpineJs::event(JsEvent::TABLE_UPDATED, $this->getListComponentName()))
);
}
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\Support\AlpineJs;
use MoonShine\Support\Enums\JsEvent;
use MoonShine\Support\ListOf;
use MoonShine\UI\Components\ActionButton;
class PostResource extends ModelResource
{
// ...
protected function topButtons(): ListOf
{
return parent::topButtons()->add(
ActionButton::make('Refresh', '#')
->dispatchEvent(AlpineJs::event(JsEvent::TABLE_UPDATED, $this->getListComponentName()))
);
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\Support\AlpineJs;
use MoonShine\Support\Enums\JsEvent;
use MoonShine\Support\ListOf;
use MoonShine\UI\Components\ActionButton;
class PostResource extends ModelResource
{
// ...
protected function topButtons(): ListOf
{
return parent::topButtons()->add(
ActionButton::make('Refresh', '#')
->dispatchEvent(AlpineJs::event(JsEvent::TABLE_UPDATED, $this->getListComponentName()))
);
}
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\Support\AlpineJs;
use MoonShine\Support\Enums\JsEvent;
use MoonShine\Support\ListOf;
use MoonShine\UI\Components\ActionButton;
class PostResource extends ModelResource
{
// ...
protected function topButtons(): ListOf
{
return parent::topButtons()->add(
ActionButton::make('Refresh', '#')
->dispatchEvent(AlpineJs::event(JsEvent::TABLE_UPDATED, $this->getListComponentName()))
);
}
}
You can also change the button display, showing them inline or in a dropdown menu to save space.
namespace App\MoonShine\Resources;
use MoonShine\Support\ListOf;
use MoonShine\UI\Components\ActionButton;
class PostResource extends ModelResource
{
protected function indexButtons(): ListOf
{
return parent::indexButtons()->prepend(
ActionButton::make('Button 1', '/')
->showInLine(),
ActionButton::make('Button 2', '/')
->showInDropdown(),
);
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Support\ListOf;
use MoonShine\UI\Components\ActionButton;
class PostResource extends ModelResource
{
// ...
protected function indexButtons(): ListOf
{
return parent::indexButtons()->prepend(
ActionButton::make('Button 1', '/')
->showInLine(),
ActionButton::make('Button 2', '/')
->showInDropdown(),
);
}
}
namespace App\MoonShine\Resources;
use MoonShine\Support\ListOf;
use MoonShine\UI\Components\ActionButton;
class PostResource extends ModelResource
{
// ...
protected function indexButtons(): ListOf
{
return parent::indexButtons()->prepend(
ActionButton::make('Button 1', '/')
->showInLine(),
ActionButton::make('Button 2', '/')
->showInDropdown(),
);
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Support\ListOf;
use MoonShine\UI\Components\ActionButton;
class PostResource extends ModelResource
{
// ...
protected function indexButtons(): ListOf
{
return parent::indexButtons()->prepend(
ActionButton::make('Button 1', '/')
->showInLine(),
ActionButton::make('Button 2', '/')
->showInDropdown(),
);
}
}
namespace App\MoonShine\Resources;
use MoonShine\Support\ListOf;
use MoonShine\UI\Components\ActionButton;
class PostResource extends ModelResource
{
// ...
protected function indexButtons(): ListOf
{
return parent::indexButtons()->prepend(
ActionButton::make('Button 1', '/')
->showInLine(),
ActionButton::make('Button 2', '/')
->showInDropdown(),
);
}
}
To modify the main component of IndexPage
, FormPage
, or DetailPage
from the resource, you can override the corresponding methods modifyListComponent()
, modifyFormComponent()
, and modifyDetailComponent()
.
use MoonShine\Contracts\UI\ComponentContract;
public function modifyListComponent(ComponentContract $component): ComponentContract
{
return parent::modifyListComponent($component)->customAttributes([
'data-my-attr' => 'value'
]);
}
namespaces
use MoonShine\Contracts\UI\ComponentContract;
public function modifyListComponent(ComponentContract $component): ComponentContract
{
return parent::modifyListComponent($component)->customAttributes([
'data-my-attr' => 'value'
]);
}
use MoonShine\Contracts\UI\ComponentContract;
public function modifyListComponent(ComponentContract $component): ComponentContract
{
return parent::modifyListComponent($component)->customAttributes([
'data-my-attr' => 'value'
]);
}
namespaces
use MoonShine\Contracts\UI\ComponentContract;
public function modifyListComponent(ComponentContract $component): ComponentContract
{
return parent::modifyListComponent($component)->customAttributes([
'data-my-attr' => 'value'
]);
}
use MoonShine\Contracts\UI\ComponentContract;
public function modifyListComponent(ComponentContract $component): ComponentContract
{
return parent::modifyListComponent($component)->customAttributes([
'data-my-attr' => 'value'
]);
}
use MoonShine\Contracts\UI\ComponentContract;
use MoonShine\UI\Components\FlexibleRender;
public function modifyFormComponent(ComponentContract $component): ComponentContract
{
return parent::modifyFormComponent($component)->fields([
FlexibleRender::make('Top'),
...parent::modifyFormComponent($component)->getFields()->toArray(),
FlexibleRender::make('Bottom'),
])->submit('Go');
}
namespaces
use MoonShine\Contracts\UI\ComponentContract;
use MoonShine\UI\Components\FlexibleRender;
public function modifyFormComponent(ComponentContract $component): ComponentContract
{
return parent::modifyFormComponent($component)->fields([
FlexibleRender::make('Top'),
...parent::modifyFormComponent($component)->getFields()->toArray(),
FlexibleRender::make('Bottom'),
])->submit('Go');
}
use MoonShine\Contracts\UI\ComponentContract;
use MoonShine\UI\Components\FlexibleRender;
public function modifyFormComponent(ComponentContract $component): ComponentContract
{
return parent::modifyFormComponent($component)->fields([
FlexibleRender::make('Top'),
...parent::modifyFormComponent($component)->getFields()->toArray(),
FlexibleRender::make('Bottom'),
])->submit('Go');
}
namespaces
use MoonShine\Contracts\UI\ComponentContract;
use MoonShine\UI\Components\FlexibleRender;
public function modifyFormComponent(ComponentContract $component): ComponentContract
{
return parent::modifyFormComponent($component)->fields([
FlexibleRender::make('Top'),
...parent::modifyFormComponent($component)->getFields()->toArray(),
FlexibleRender::make('Bottom'),
])->submit('Go');
}
use MoonShine\Contracts\UI\ComponentContract;
use MoonShine\UI\Components\FlexibleRender;
public function modifyFormComponent(ComponentContract $component): ComponentContract
{
return parent::modifyFormComponent($component)->fields([
FlexibleRender::make('Top'),
...parent::modifyFormComponent($component)->getFields()->toArray(),
FlexibleRender::make('Bottom'),
])->submit('Go');
}
use MoonShine\Contracts\UI\ComponentContract;
public function modifyDetailComponent(ComponentContract $component): ComponentContract
{
return parent::modifyDetailComponent($component)->customAttributes([
'data-my-attr' => 'value'
]);
}
namespaces
use MoonShine\Contracts\UI\ComponentContract;
public function modifyDetailComponent(ComponentContract $component): ComponentContract
{
return parent::modifyDetailComponent($component)->customAttributes([
'data-my-attr' => 'value'
]);
}
use MoonShine\Contracts\UI\ComponentContract;
public function modifyDetailComponent(ComponentContract $component): ComponentContract
{
return parent::modifyDetailComponent($component)->customAttributes([
'data-my-attr' => 'value'
]);
}
namespaces
use MoonShine\Contracts\UI\ComponentContract;
public function modifyDetailComponent(ComponentContract $component): ComponentContract
{
return parent::modifyDetailComponent($component)->customAttributes([
'data-my-attr' => 'value'
]);
}
use MoonShine\Contracts\UI\ComponentContract;
public function modifyDetailComponent(ComponentContract $component): ComponentContract
{
return parent::modifyDetailComponent($component)->customAttributes([
'data-my-attr' => 'value'
]);
}
The best way to change page components is to publish the pages and interact through them.
But, if you want to quickly add components to pages, you can use the resource methods pageComponents()
, indexPageComponents()
, formPageComponents()
and detailPageComponents()
.
use MoonShine\Core\Collections\Components;
use MoonShine\UI\Components\FormBuilder;
use MoonShine\UI\Components\Modal;
use MoonShine\UI\Fields\Text;
protected function pageComponents(): array
{
return [
Modal::make(
'My Modal'
components: Components::make([
FormBuilder::make()->fields([
Text::make('Title')
])
])
)
->name('demo-modal')
];
}
namespaces
use MoonShine\Core\Collections\Components;
use MoonShine\UI\Components\FormBuilder;
use MoonShine\UI\Components\Modal;
use MoonShine\UI\Fields\Text;
// or indexPageComponents/formPageComponents/detailPageComponents
protected function pageComponents(): array
{
return [
Modal::make(
'My Modal'
components: Components::make([
FormBuilder::make()->fields([
Text::make('Title')
])
])
)
->name('demo-modal')
];
}
use MoonShine\Core\Collections\Components;
use MoonShine\UI\Components\FormBuilder;
use MoonShine\UI\Components\Modal;
use MoonShine\UI\Fields\Text;
// or indexPageComponents/formPageComponents/detailPageComponents
protected function pageComponents(): array
{
return [
Modal::make(
'My Modal'
components: Components::make([
FormBuilder::make()->fields([
Text::make('Title')
])
])
)
->name('demo-modal')
];
}
namespaces
use MoonShine\Core\Collections\Components;
use MoonShine\UI\Components\FormBuilder;
use MoonShine\UI\Components\Modal;
use MoonShine\UI\Fields\Text;
// or indexPageComponents/formPageComponents/detailPageComponents
protected function pageComponents(): array
{
return [
Modal::make(
'My Modal'
components: Components::make([
FormBuilder::make()->fields([
Text::make('Title')
])
])
)
->name('demo-modal')
];
}
use MoonShine\Core\Collections\Components;
use MoonShine\UI\Components\FormBuilder;
use MoonShine\UI\Components\Modal;
use MoonShine\UI\Fields\Text;
// or indexPageComponents/formPageComponents/detailPageComponents
protected function pageComponents(): array
{
return [
Modal::make(
'My Modal'
components: Components::make([
FormBuilder::make()->fields([
Text::make('Title')
])
])
)
->name('demo-modal')
];
}
Components will be added to bottomLayer
.
Resource
has several different methods to connect to various parts of its lifecycle. Let's walk through them:
The onLoad()
method allows integration at the moment when the resource is loaded and currently active.
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected function onLoad(): void
{
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function onLoad(): void
{
// ...
}
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function onLoad(): void
{
// ...
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function onLoad(): void
{
// ...
}
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function onLoad(): void
{
// ...
}
}
You can also attach a trait
to the resource and within the trait
, add a method according to the naming convention - load{TraitName}
and use the trait to access the onLoad
of the resource.
namespace App\MoonShine\Resources;
use App\Traits\WithPermissions;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
use WithPermissions;
}
namespaces
namespace App\MoonShine\Resources;
use App\Traits\WithPermissions;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
use WithPermissions;
// ...
}
namespace App\MoonShine\Resources;
use App\Traits\WithPermissions;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
use WithPermissions;
// ...
}
namespaces
namespace App\MoonShine\Resources;
use App\Traits\WithPermissions;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
use WithPermissions;
// ...
}
namespace App\MoonShine\Resources;
use App\Traits\WithPermissions;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
use WithPermissions;
// ...
}
use MoonShine\Support\Enums\Layer;
use MoonShine\Support\Enums\PageType;
trait WithPermissions
{
protected function loadWithPermissions(): void
{
$this->getPages()
->findByUri(PageType::FORM->value)
->pushToLayer(
layer: Layer::BOTTOM,
component: Permissions::make(
label: 'Permissions',
resource: $this,
)
);
}
}
namespaces
use MoonShine\Support\Enums\Layer;
use MoonShine\Support\Enums\PageType;
trait WithPermissions
{
protected function loadWithPermissions(): void
{
$this->getPages()
->findByUri(PageType::FORM->value)
->pushToLayer(
layer: Layer::BOTTOM,
component: Permissions::make(
label: 'Permissions',
resource: $this,
)
);
}
}
use MoonShine\Support\Enums\Layer;
use MoonShine\Support\Enums\PageType;
trait WithPermissions
{
protected function loadWithPermissions(): void
{
$this->getPages()
->findByUri(PageType::FORM->value)
->pushToLayer(
layer: Layer::BOTTOM,
component: Permissions::make(
label: 'Permissions',
resource: $this,
)
);
}
}
namespaces
use MoonShine\Support\Enums\Layer;
use MoonShine\Support\Enums\PageType;
trait WithPermissions
{
protected function loadWithPermissions(): void
{
$this->getPages()
->findByUri(PageType::FORM->value)
->pushToLayer(
layer: Layer::BOTTOM,
component: Permissions::make(
label: 'Permissions',
resource: $this,
)
);
}
}
use MoonShine\Support\Enums\Layer;
use MoonShine\Support\Enums\PageType;
trait WithPermissions
{
protected function loadWithPermissions(): void
{
$this->getPages()
->findByUri(PageType::FORM->value)
->pushToLayer(
layer: Layer::BOTTOM,
component: Permissions::make(
label: 'Permissions',
resource: $this,
)
);
}
}
The onBoot
method allows integration at the moment when MoonShine is creating an instance of the resource within the system.
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
protected function onBoot(): void
{
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function onBoot(): void
{
// ...
}
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function onBoot(): void
{
// ...
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function onBoot(): void
{
// ...
}
}
namespace App\MoonShine\Resources;
use MoonShine\Laravel\Resources\ModelResource;
class PostResource extends ModelResource
{
// ...
protected function onBoot(): void
{
// ...
}
}
You can also attach a trait
to the resource and within the trait
, add a method according to the naming convention - boot{TraitName}
and use the trait to access the onBoot()
of the resource.
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
protected function onLoad(): void
{
$this->getAssetManager()
->add(Css::make('/css/app.css'))
->append(Js::make('/js/app.js'));
}
namespaces
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
protected function onLoad(): void
{
$this->getAssetManager()
->add(Css::make('/css/app.css'))
->append(Js::make('/js/app.js'));
}
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
protected function onLoad(): void
{
$this->getAssetManager()
->add(Css::make('/css/app.css'))
->append(Js::make('/js/app.js'));
}
namespaces
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
protected function onLoad(): void
{
$this->getAssetManager()
->add(Css::make('/css/app.css'))
->append(Js::make('/js/app.js'));
}
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
protected function onLoad(): void
{
$this->getAssetManager()
->add(Css::make('/css/app.css'))
->append(Js::make('/js/app.js'));
}
If the resource is in async
mode, then you can modify the answer:
public function modifyDestroyResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifyMassDeleteResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifySaveResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifyDestroyResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifyMassDeleteResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifySaveResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifyDestroyResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifyMassDeleteResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifySaveResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifyDestroyResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifyMassDeleteResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifySaveResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifyDestroyResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifyMassDeleteResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}
public function modifySaveResponse(MoonShineJsonResponse $response): MoonShineJsonResponse
{
return $response;
}