- Basics
- Creating a Page
- Title
- Components
- Breadcrumbs
- Layout
- Alias
- Rendering
- Before Rendering
- Response Modifier
- Lifecycle
- Creating a Link to a Page from a Resource
- Assets
Basics
Page
is the foundation of the MoonShine admin panel. The main purpose of Page
is to display components.
Pages with similar logic can be combined into a Resource
.
Creating a Page
To create a page class, you can use the console command:
php artisan moonshine:page
php artisan moonshine:page
After entering the class name, a file will be created that serves as the basis for the page in the admin panel.
By default, it is located in the app/MoonShine/Pages
directory.
You can learn about all supported options in the section Commands.
Pages are automatically registered in the system when the command is executed, but if you create a page manually,
it must be registered in the MoonShineServiceProvider
in the $core->pages()
method.
Title
The page title can be set through the $title
property, and the subtitle can be set through $subtitle
.
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{protected string $title = 'CustomPage';protected string $subtitle = 'Subtitle';// ...}
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{protected string $title = 'CustomPage';protected string $subtitle = 'Subtitle';// ...}
If some logic is required for the title and subtitle, the title()
and subtitle()
methods allow you to implement it.
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{// ...public function getTitle(): string{return $this->title ?: 'CustomPage';}public function getSubtitle(): string{return $this->subtitle ?: 'Subtitle';}}
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{// ...public function getTitle(): string{return $this->title ?: 'CustomPage';}public function getSubtitle(): string{return $this->subtitle ?: 'Subtitle';}}
Components
To register the components of the page, the components()
method is used.
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;use MoonShine\UI\Components\Layout\Box;use MoonShine\UI\Components\Layout\Column;use MoonShine\UI\Components\Layout\Grid;class CustomPage extends Page{// ...protected function components(): iterable{return [Grid::make([Column::make([Box::make([// ...])])->columnSpan(6),Column::make([Box::make([// ...])])->columnSpan(6),])];}}
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;use MoonShine\UI\Components\Layout\Box;use MoonShine\UI\Components\Layout\Column;use MoonShine\UI\Components\Layout\Grid;class CustomPage extends Page{// ...protected function components(): iterable{return [Grid::make([Column::make([Box::make([// ...])])->columnSpan(6),Column::make([Box::make([// ...])])->columnSpan(6),])];}}
For more detailed information, refer to the Components section.
Breadcrumbs
The getBreadcrumbs()
method is responsible for generating the breadcrumbs.
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{// ...public function getBreadcrumbs(): array{return ['#' => $this->getTitle()];}}
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{// ...public function getBreadcrumbs(): array{return ['#' => $this->getTitle()];}}
Layout
By default, pages use the AppLayout
or CompactLayout
display template.
For more information about templates, see the Layout section.
namespace App\MoonShine\Pages;use MoonShine\Laravel\Layouts\AppLayout;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{protected ?string $layout = AppLayout::class;// ...}
namespace App\MoonShine\Pages;use MoonShine\Laravel\Layouts\AppLayout;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{protected ?string $layout = AppLayout::class;// ...}
Modifying Layout
When developing an admin panel using MoonShine, there is often a need for flexible management of templates.
Instead of creating numerous separate templates for various situations, MoonShine provides an opportunity to dynamically modify existing templates.
This is achieved through the modifyLayout()
method.
The modifyLayout()
method allows you to access the template after creating its instance and make necessary changes.
This is especially useful when you need to adapt the template to specific conditions or add dynamic content.
Example usage
Consider an example from the moonshine-software/two-factor
package that demonstrates how to use modifyLayout()
for customizing the authentication template:
use MoonShine\Contracts\UI\LayoutContract;/*** @param LoginLayout $layout*/protected function modifyLayout(LayoutContract $layout): LayoutContract{return $layout->title(__('moonshine-two-factor::ui.2fa'))->description(__('moonshine-two-factor::ui.confirm'));}
use MoonShine\Contracts\UI\LayoutContract;/*** @param LoginLayout $layout*/protected function modifyLayout(LayoutContract $layout): LayoutContract{return $layout->title(__('moonshine-two-factor::ui.2fa'))->description(__('moonshine-two-factor::ui.confirm'));}
Alias
If you need to change the page alias, this can be done through the $alias
property.
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{protected ?string $alias = null;// ...}
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{protected ?string $alias = null;// ...}
You can also override the getAlias()
method.
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{public function getAlias(): ?string{return 'custom_page';}// ...}
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{public function getAlias(): ?string{return 'custom_page';}// ...}
Rendering
You can display the page outside MoonShine by simply returning it in a controller.
class ProfileController extends Controller{// ...public function __invoke(ProfilePage $page): ProfilePage{return $page->loaded();}}
class ProfileController extends Controller{// ...public function __invoke(ProfilePage $page): ProfilePage{return $page->loaded();}}
Or with Fortify
Fortify::loginView(static fn() => app(ProfilePage::class));
Fortify::loginView(static fn() => app(ProfilePage::class));
Before Rendering
The prepareBeforeRender()
method allows you to execute actions before displaying the page.
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{protected function prepareBeforeRender(): void{parent::prepareBeforeRender();if (auth()->user()->moonshine_user_role_id !== MoonshineUserRole::DEFAULT_ROLE_ID) {abort(403);}}}
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class CustomPage extends Page{protected function prepareBeforeRender(): void{parent::prepareBeforeRender();if (auth()->user()->moonshine_user_role_id !== MoonshineUserRole::DEFAULT_ROLE_ID) {abort(403);}}}
Response Modifier
By default, the page is rendered through the PageController
, invoking the render()
method.
However, there are times when it's necessary to change the standard response, such as redirecting under certain conditions.
In such cases, the modifyResponse()
method can be used.
The modifyResponse()
method allows you to modify the page response before it is sent.
Here’s an example of its usage:
use Symfony\Component\HttpFoundation\Response;protected function modifyResponse(): ?Response{if (request()->has('id')) {return redirect()->to('/admin/article-resource/index-page');}return null;}
use Symfony\Component\HttpFoundation\Response;protected function modifyResponse(): ?Response{if (request()->has('id')) {return redirect()->to('/admin/article-resource/index-page');}return null;}
Using modifyResponse()
provides a flexible way to manage the page response, allowing for complex request and response handling logic in the admin panel.
Lifecycle
Page
has several different methods to hook into various parts of its lifecycle. Let’s go through them:
Active Page
The onLoad()
method allows integration at the moment when the page is loaded and is currently active.
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class PostPage extends Page{// ...protected function onLoad(): void{parent::onLoad();// ...}}
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class PostPage extends Page{// ...protected function onLoad(): void{parent::onLoad();// ...}}
Booting Instance
The booted()
method allows integration at the moment when MoonShine creates an instance of the page in the system.
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class PostPage extends Page{// ...protected function booted(): void{parent::booted();// ...}}
namespace App\MoonShine\Pages;use MoonShine\Laravel\Pages\Page;class PostPage extends Page{// ...protected function booted(): void{parent::booted();// ...}}
Creating a Link to a Page from a Resource
In this example, to create a link to a new page, we'll use the ActionButton and the getPageUrl method.
use MoonShine\Support\ListOf;use MoonShine\UI\Components\ActionButton;/*** @throws Throwable*/public function indexButtons(): ListOf{return parent::indexButtons()->add(ActionButton::make('To custom page',url: fn($model) => $this->getPageUrl(PostPage::class, params: ['resourceItem' => $model->getKey()]),),);}
use MoonShine\Support\ListOf;use MoonShine\UI\Components\ActionButton;/*** @throws Throwable*/public function indexButtons(): ListOf{return parent::indexButtons()->add(ActionButton::make('To custom page',url: fn($model) => $this->getPageUrl(PostPage::class, params: ['resourceItem' => $model->getKey()]),),);}
Assets
use MoonShine\AssetManager\Css;use MoonShine\AssetManager\Js;protected function onLoad(): void{parent::onLoad();$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{parent::onLoad();$this->getAssetManager()->add(Css::make('/css/app.css'))->append(Js::make('/js/app.js'));}