Een aangepast beheerdersoverzicht bouwen in Sulu
22 januari 2024
5 minutes
Een van de minder bekende functies in de Sulu Admin is dat je aangepaste admin views kunt bouwen in je Sulu Admin interface. Dit kan handig zijn in gevallen waarin je een pagina wilt maken die er anders uitziet dan de standaard lijsten en formulieren. In deze blog laten we je de basisstappen zien van waaruit je je verkenningstocht kunt beginnen.
Beslissen waar u de aangepaste weergave wilt plaatsen
Er zijn 2 plaatsen waar u een aangepaste weergave kunt plaatsen:
Als een pagina die direct toegankelijk is vanuit de navigatie.
Als een extra tabblad binnen de bewerkingsweergaven.
Het startpunt voor het registreren van de aangepaste weergaven is de Admin-klasse. U kunt de weergaven als volgt configureren:
final class SomeAdmin extends Admin
{
private const MY_VIEW_TYPE = 'app.my_custom_view_name';
public function __construct(
private readonly ViewBuilderFactoryInterface $viewBuilderFactory,
) {
}
public function configureViews(ViewCollection $viewCollection): void
{
// As a page:
$viewCollection->add(
$this->viewBuilderFactory->createViewBuilder(
name: self::MY_VIEW_TYPE,
path: '/my-view',
type: self::MY_VIEW_TYPE
)
->setOption('hello', 'world')
);
// OR as an extra tab on an edit view:
$viewCollection->add(
$this->viewBuilderFactory->createTabViewBuilder(name: 'My view', path: '/my-view')
->setTabPriority(-100)
->setParent(self::EDIT_FORM_VIEW)
->setType(self::MY_VIEW_TYPE)
->setOption('hello', 'world')
);
}
}
Er zijn 2 belangrijke dingen op te merken uit de configuratie:
Het view type wordt gebruikt om het React component dat je wilt koppelen te identificeren. Het is een unieke identifier die het PHP gedeelte van de admin koppelt met het React gedeelte van de admin.
U kunt elke gewenste optie doorgeven in de aangepaste React-weergave. Deze opties worden beschikbaar gemaakt in uw aangepaste React-weergave. Een veel voorkomende toepassing voor deze opties is het doorgeven van de admin resource identifiers die kunnen worden gebruikt om gegevens te laden. Een ander gebruik kan een zeer specifieke instelling zijn uit uw PHP-configuratie die u wilt doorgeven aan uw frontend.
Je eerste beheerdersweergave bouwen
In de vorige configuratie hebben we een uniek beheerderstype opgegeven dat zal worden gebruikt als identifier van de aangepaste weergave. Om de identifier te koppelen aan een react component, kunt u deze op deze manier registreren in sulu's view register:
// assets/admin/app.ts
import {viewRegistry} from 'sulu-admin-bundle/containers';
viewRegistry.add('app.my_custom_view_name', MyCustomViewComponent);
De React component die hier gelinkt wordt, ziet er zo uit:
import React, {Component} from 'react';
import {ViewProps} from 'sulu-admin-bundle/containers';
import View from 'sulu-admin-bundle/components/View';
export interface RouteOptions {
readonly hello: string;
}
interface Props extends ViewProps<RouteOptions> {
}
class MyCustomViewComponent extends Component<Props> {
render() {
return <View>
<div>Hello {this.props.route.options.hello}</div>
</View>
}
}
De RouteOptions
vertegenwoordigen de opties die vanuit de PHP Admin configuratie worden doorgegeven aan de React eigenschappen. In dit geval kan het worden gebruikt om Hello world
weer te geven, omdat we world
hebben doorgegeven als waarde voor de hello
optie. De View component wordt geleverd door sulu en is er alleen om wat basisstyling te geven aan de view. Vanaf daar kun je er alles mee doen wat je wilt.
Het meer interactief maken
Je hebt misschien gemerkt dat we in ons kleine voorbeeld een ouderwetse class component hebben gebruikt in plaats van een functionele component. Het is perfect mogelijk om ook een functionele component te gebruiken, maar sulu wordt geleverd met een oudere versie van mobx die nog niet volledig compatibel is met de functionele componenten.
Mobx is een framework dat bovenop React gebruikt kan worden om state te beheren. Het werkt op basis van observers die luisteren naar veranderingen op waarneembare waarden. Als de geobserveerde waarde verandert, zal de observer de component rerenderen die op veranderingen let.
Laten we een klein voorbeeld maken:
import {observable} from "mobx";
import {observer} from 'mobx-react';
@observer
class MyCustomViewComponent extends Component<Props> {
@observable messageOfTheDay : MessageOfTheDay;
constructor(props: Props) {
super(props);
this.messageOfTheDay = new MessageOfTheDay();
}
render() {
return <View>
<div>Hello {this.props.route.options.hello}</div>
{!this.messageOfTheDay.loading && <div>{this.messageOfTheDay.value}</div>}
</View>
}
}
Een decorator wordt gebruikt om de custom view component te laten luisteren naar veranderingen op de messageOfTheDay
eigenschap. Wanneer de component wordt gebouwd, wordt het bericht van de dag opgehaald uit een asynchrone bron. Zodra de gegevens zijn geladen, zal de observer merken dat het laden is gestopt, en dat de gegevens er zijn. De component wordt opnieuw weergegeven en het bericht van de dag wordt getoond.
Om dit alles te laten werken, moet de MessageOfTheDay
component ook observeerbare waarden bevatten.
Een implementatie zou er zo uit kunnen zien:
import {action, observable, runInAction} from "mobx";
import {observer} from 'mobx-react';
class MessageOfTheDay {
@observable value : string|undefined = undefined;
@observable loading : boolean = true;
public constructor() {
this.fetch();
}
@action
public async fetch() {
this.loading = true;
this.value = undefined;
try {
const messageOfTheDay = await loadMessageOfTheDayFromServer()
runInAction(() => {
this.loading = false;
this.value = messageOfTheDay;
})
} catch (error) {
runInAction(() => {
this.loading = false
})
}
}
}
Sulu biedt een higher order component aan die het mogelijk maakt om ook een aangepaste werkbalk te configureren voor uw aangepaste weergave. Stel in ons voorbeeld hierboven dat we een synchronisatieknop willen toevoegen die een ander willekeurig bericht van de dag ophaalt van de server. Dit kan worden gedaan door een refresh-actie toe te voegen aan de werkbalk zoals deze:
import { withToolbar} from 'sulu-admin-bundle/containers';
export default withToolbar(MyCustomViewComponent, function (this: MyCustomViewComponent): ToolbarConfig {
return {
items: [
{
type: 'button',
label: 'Refresh',
icon: 'su-sync',
disabled: this.messageOfTheDay.loading,
onClick: async () => {
return await this.messageOfTheDay.fetch();
},
}
]
};
})
Het bovenstaande voorbeeld laat zien dat je je aangepaste weergavecomponent kunt versieren om werkbalkacties aan te bieden. Je aangepaste component wordt ook opgenomen in de werkbalkconfigurator. Zo kun je de eigenschappen van je aangepaste component gebruiken als invoer voor een uitgeschakelde eigenschap of als doel van een actie zoals het herladen van het bericht.