Integrating an App Layout
In deze stap haal je alle onderdelen van je applicatie samen in een samenhangend app-lay-out. Aan het einde van deze stap zal de structuur van je app nauw aansluiten bij het SideMenu archetype, en je zult een beter inzicht hebben in hoe de volgende componenten en concepten werken:
De app uitvoeren
Tijdens het ontwikkelen van je app kun je 6-integrating-an-app-layout gebruiken als vergelijkingspunt. Om de app in actie te zien:
-
Navigeer naar de hoogste map met het
pom.xml-bestand, dit is6-integrating-an-app-layoutals je de versie op GitHub volgt. -
Gebruik de volgende Maven-opdracht om de Spring Boot-app lokaal uit te voeren:
mvn
Het uitvoeren van de app opent automatisch een nieuwe browser op http://localhost:8080.
Een herbruikbare component maken
In een eerdere stap, Routing en Composieten, heb je twee composietcomponenten gemaakt die de inhoud van de klantentabel en het klantformulier bevatten. Als onderdeel van deze stap maak je een kleinere, herbruikbare composietcomponent om de naam van de app in het zijmenu en een over ons-pagina weer te geven. Als je in de toekomst de naam van de app wilt wijzigen, hoef je deze alleen in deze component bij te werken.
In src/main/java/com/webforj/tutorial/components, maak een klasse genaamd AppTitle. De gebonden component voor AppTitle zal een FlexLayout zijn, een containercomponent die in deze stap wordt gebruikt om je te laten zien hoe je complexere lay-outs maakt. Voor deze FlexLayout arrangeer je de richting van de items en de ruimte tussen de items. Dat doe je door respectievelijk de methodes setDirection() en setSpacing() te gebruiken.
// Maak de gebonden component een FlexLayout
public class AppTitle extends Composite<FlexLayout> {
private FlexLayout self = getBoundComponent();
public AppTitle() {
// Rangschik de items verticaal
self.setDirection(FlexDirection.COLUMN);
// Stel de afstand tussen de items in
self.setSpacing("0px");
}
}
Gebruik vervolgens standaard HTML-elementen om de titel en subtitel te maken. Door de onderste marge van een koptekst-element in te stellen op 0px breng je de elementen dichter bij elkaar, en je kunt de subtitel opmaken met behulp van DWC CSS-variabelen.
public class AppTitle extends Composite<FlexLayout> {
private FlexLayout self = getBoundComponent();
private H2 title = new H2("Klantbeheer");
private Paragraph subTitle = new Paragraph("Een Eenvoudig Registratiesysteem");
public AppTitle() {
title.setStyle("margin-bottom", "0px");
subTitle.setStyle("color", "var(--dwc-color-gray-50)");
subTitle.setStyle("font-size", "var(--dwc-font-size-m)");
self.setDirection(FlexDirection.COLUMN)
.setSpacing("0px")
.add(title, subTitle);
}
}
Optionele weergave
Hoewel AppTitle eenvoudig is, maakt het toevoegen van een booleaanse parameter aan de constructor het mogelijk om te controleren wanneer bepaalde delen van de component moeten worden weergegeven, zoals de subtitel.
// Voeg een booleaanse parameter toe
public AppTitle(boolean showSubTitle) {
self.setDirection(FlexDirection.COLUMN)
.setSpacing("0px")
// Voeg de titel standaard toe
.add(title);
// Optioneel de subtitel weergeven
if (showSubTitle) {
self.add(subTitle);
}
}
Voltooide AppTitle
Al met al zou de herbruikbare component er als volgt uit moeten zien:
public class AppTitle extends Composite<FlexLayout> {
private FlexLayout self = getBoundComponent();
private H2 title = new H2("Klantbeheer");
private Paragraph subTitle = new Paragraph("Een Eenvoudig Registratiesysteem");
public AppTitle(boolean showSubTitle) {
title.setStyle("margin-bottom", "0");
subTitle.setStyle("color", "var(--dwc-color-gray-50)");
subTitle.setStyle("font-size", "var(--dwc-font-size-m)");
self.setDirection(FlexDirection.COLUMN)
.setSpacing("0px")
.add(title);
if (showSubTitle) {
self.add(subTitle);
}
}
}
Een over ons-pagina maken
De eerste plaats waar je de nieuw gemaakte AppTitle-component wilt toevoegen, is een over ons-pagina. Deze pagina bevat een afbeelding en de AppTitle-component, gecentreerd op de pagina met behulp van een andere FlexLayout.
Inhoud centreren met een FlexLayout
Het doel is om de inhoud van de over ons-pagina te centreren met behulp van de FlexLayout. De FlexLayout-component volgt het CSS flexbox lay-outmodel. Methoden voor de FlexLayout, zoals de eerder gebruikte om de items in een kolom te oriënteren, zijn verschillende manieren om de items te rangschikken.
De methoden voor het rangschikken van items in een FlexLayout gebruiken een relatief richting systeem. In plaats van te denken aan de horizontale en verticale assen, is het beter om de as parallel aan de items als de hoofd-as te beschouwen en de as loodrecht op de items als de kruis-as.
Door zowel de FlexJustifyContent als de FlexAlignment eigenschappen in te stellen op CENTER, worden de items langs zowel de hoofd- als de kruis-assen gecentreerd in de FlexLayout, en door de FlexLayout de volledige ruimte van zijn bovenliggende container te laten innemen, wordt het gecentreerd op de pagina.
private final FlexLayout layout = new FlexLayout();
// Vul de gehele ruimte van het bovenliggende element
layout.setSize("100%", "100%");
// Maak de hoofd-as verticaal
layout.setDirection(FlexDirection.COLUMN);
// Centreer de items langs de kruis-as
layout.setAlignment(FlexAlignment.CENTER);
// Centreer de items langs de hoofd-as
layout.setJustifyContent(FlexJustifyContent.CENTER);
Om te helpen visualiseren hoe de verschillende methoden werken, kijk eens naar de blogpost FlexWrap your mind around webforJ's FlexLayout.
Hulpbronnen toevoegen
Een van de items die in de gecentreerde FlexLayout zal komen, is een afbeelding. Voor deze tutorial kun je de afbeelding van de over ons-pagina bekijken en downloaden op GitHub. Zodra je deze hebt gedownload, voeg je deze toe aan de statische map van je project in src/main/resources/static/images en noem je deze Files.svg.
Door deze afbeelding in de statische map te plaatsen kun je deze refereren met behulp van het Webserverprotocol. Vervolgens kun je deze binnen je app gebruiken als een HTML-element, zoals:
private Img fileImg = new Img("ws://images/Files.svg");
De AboutView maken
Net als de twee bestaande app-pagina's zal de over ons-pagina een routable view zijn. In src/main/java/com/webforj/tutorial/views, voeg een klasse genaamd AboutView toe. Gebruik een FlexLayout voor de gebonden component, net zoals je deed voor AppTitle.
Aangezien je de klasse AboutView hebt genoemd, is er geen noodzaak om een aangepaste waarde voor de URL-mapping op te geven; deze pagina wordt standaard weergegeven op http://localhost:8080/about.
Hier is hoe het eruit ziet wanneer je de concepten uit de vorige stappen gebruikt met de nieuw gemaakte componenten om een nieuwe view met gecentreerde inhoud te creëren:
@Route()
@FrameTitle("Over")
public class AboutView extends Composite<FlexLayout> {
private FlexLayout self = getBoundComponent();
private Img fileImg = new Img("ws://images/Files.svg");
public AboutView() {
fileImg.setWidth(250);
self.setSize("100%", "100%")
.setDirection(FlexDirection.COLUMN)
.setAlignment(FlexAlignment.CENTER)
.setJustifyContent(FlexJustifyContent.CENTER)
.add(fileImg, new AppTitle(false));
}
}
De Layout route maken
Het wordt kort genoemd in de stap Routing en Composieten, maar er zijn twee route types. MainView, FormView, en AboutView zijn allemaal View routes, terwijl het route type dat je zult gebruiken om het zijmenu van de app te maken een Layout route is.
Lay-outroutes wikkelen kindviews en maken het mogelijk dat bepaalde UI-onderdelen behouden blijven tussen views, zoals een zijmenu. In src/main/java/com/webforj/tutorial/layouts, creëer een klasse genaamd MainLayout.
Route-uitgangen
Net als de view-routes heeft MainLayout een @Route-annotatie nodig. Omdat het echter een suffix Layout heeft en lay-outroutes niet bijdragen aan de URL, hoeft deze annotatie geen argumenten te hebben.
@Route
public class MainLayout {
public MainLayout() {
}
}
De app weet welke views binnen MainLayout moeten worden weergegeven door de lay-outklasse als de route-uitgang in elke view te declareren. De vorige stappen hebben alleen een value-eigenschap ingesteld in de @Route-annotaties, dus nu moet je expliciet aangeven wat de value- en outlet-eigenschappen zijn voor de view-klassen.
- MainView
- FormView
- AboutView
@Route(value = "/", outlet = MainLayout.class)
@Route(value = "customer/:id?<[0-9]+>", outlet = MainLayout.class)
@Route(outlet = MainLayout.class)
Dit is de laatste wijziging die nodig is voor FormView en AboutView in deze stap, dus vergeet niet om de @Route-annotatie voor die views bij te werken voordat je je app uitvoert.
Het gebruik van de AppLayout component
Nu je app de views binnen MainLayout weergeeft, kun je kiezen waar die componenten worden weergegeven. Door de AppLayout als de gebonden component voor MainLayout te kiezen, kun je de views standaard in een hoofdinhoudsgebied opslaan, terwijl je ook verschillende gebieden hebt om items voor de kop en het zijmenu toe te voegen.
Slots
Voor veel webforJ-containers voegt het gebruik van de add()-methoden UI-componenten toe aan het hoofdinhoudsgebied. In de AppLayout-component zijn er meerdere gebieden voor het toevoegen van UI-componenten, elk in een aparte slot. Door MainLayout als een lay-outroute te markeren en de gebonden component als een AppLayout in te stellen, worden de views automatisch in de hoofdinhoudsslot weergegeven.
In deze stap zul je de drawer-title en drawer slots gebruiken om een zijmenu te creëren, en de header slot om weer te geven welke pagina de gebruiker op dat moment bekijkt en een schakelaar voor het zijmenu.
Een zijmenu maken
Wanneer er voldoende schermruimte op het apparaat is, toont de AppLayout-component een lade. Dit is waar je opnieuw de AppTitle toevoegt en items die gebruikers in de app laten navigeren.
Standaard toont AppLayout geen ladekop, maar met behulp van de methode setDrawerHeaderVisible() kun je items weergeven die zich binnen de drawer-title slot bevinden, wat de AppTitle zal zijn met de subtitel weergegeven.
private AppLayout appLayout = new AppLayout();
// Toon de Ladekop
appLayout.setDrawerHeaderVisible(true);
// Voeg de AppTitle toe aan de Ladekop met zijn subtitel
appLayout.addToDrawerTitle(new AppTitle(true));
De drawer slot zou dan de componenten moeten bevatten die gebruikers in de app laten navigeren. Het gebruik van de AppNav component maakt het eenvoudig om nieuwe navigatie opties te creëren. Voor elke link hoef je alleen maar een AppNavItem te maken. De AppNavItem componenten in deze tutorial gebruiken drie parameters:
Het groeperen van alle lade-instellingen in MainLayout ziet er als volgt uit:
@Route
public class MainLayout extends Composite<AppLayout> {
private AppLayout self = getBoundComponent();
private AppNav appNav = new AppNav();
public MainLayout() {
setDrawer();
}
private void setDrawer() {
self.setDrawerHeaderVisible(true)
.addToDrawerTitle(new AppTitle(true));
appNav.addItem(new AppNavItem("Dashboard", MainView.class,
TablerIcon.create("archive")));
appNav.addItem(new AppNavItem("Over", AboutView.class,
TablerIcon.create("info-circle")));
self.addToDrawer(appNav);
}
Een hoofdkop maken
De header slot zou twee items moeten bevatten: een schakelaar om het zijmenu te tonen of te verbergen en een manier om de titel van het frame weer te geven. Beide items zullen binnen een Toolbar component worden geplaatst, een andere manier om componenten te organiseren.
Je kunt de schakelaar voor de AppLayout lade opnemen met de AppDrawerToggle component. Deze component is al gestyled met een veelgebruikt pictogram voor verborgen menu-opties en richt zich op de lade om deze te openen en sluiten.
// Maak de containercomponenten
private AppLayout appLayout = new AppLayout();
private Toolbar toolbar = new Toolbar();
// Voeg de Toolbar toe aan de AppLayout hoofdkop
appLayout.addToHeader(toolbar);
// Voeg de AppDrawerToggle toe aan de toolbar
toolbar.addToStart(new AppDrawerToggle());
De hoofdkop kan ook de titel van het frame weergeven door het navigatie-evenement te gebruiken om details over de binnenkomende component op te vragen, terwijl je een gebeurtenislistener hebt om de registratie te verwijderen om geheugenlekken te voorkomen.
// Maak het H1-element en de navigatieregistratie
private H1 title = new H1("");
private ListenerRegistration<NavigateEvent> navigateRegistration;
// Registreer de gebeurtenis bij navigeren
navigateRegistration = Router.getCurrent().onNavigate(this::onNavigate);
// Verwijder listeners voordat MainLayout wordt vernietigd
@Override
protected void onDidDestroy() {
if (navigateRegistration != null) {
navigateRegistration.remove();
}
}
// Verkrijg de titel van het frame uit de binnenkomende view klasse
private void onNavigate(NavigateEvent ev) {
Component component = ev.getContext().getComponent();
if (component != null) {
FrameTitle frameTitle = component.getClass().getAnnotation(FrameTitle.class);
title.setText(frameTitle != null ? frameTitle.value() : "");
}
}
Voltooide MainLayout
Hier is MainLayout met aangemaakte inhoud voor de lade en de hoofdkop binnen een AppLayout:
Het bijwerken van FormView
Zoals eerder vermeld, was de enige wijziging aan FormView in de @Route-annotatie.
@Route(value = "customer/:id?<[0-9]+>", outlet = MainLayout.class)
Het bijwerken van MainView
Voor MainView zul je de gebonden component wijzigen van een Div naar een FlexLayout. Dit stelt je in staat om de tabel te centreren, terwijl je ook specifieke componenten in de lay-out verplaatst. Het gebruik van de methode setItemAlignment() stelt je in staat om een component in de lay-out te kiezen en deze te verplaatsen, zodat je de tabel gecentreerd kunt houden terwijl je de knop klant toevoegen naar de rechterbovenhoek van de lay-out verplaatst.
// Wijzig de gebonden component in een FlexLayout
private FlexLayout self = getBoundComponent();
// Align de knop aan het einde van de kruis-as
self.setItemAlignment(FlexAlignment.END, addCustomer);
Een andere verbetering die je hier kunt aanbrengen, is de breedte van de tabel. In plaats van een vaste breedte, kun je deze instellen om overeen te komen met zijn bovenliggende container, de FlexLayout. Dan kan die FlexLayout een maximale breedte hebben, zodat deze niet overstretched op grotere schermen.
private FlexLayout self = getBoundComponent();
private Table<Customer> table = new Table<>();
self.setSize("100%", "100%");
self.setMaxWidth(2000);
table.setSize("100%", "294px");
Door deze samen te voegen en een andere methode te maken om de FlexLayout gecentreerd te krijgen zoals de vorige, ziet MainView met de gemarkeerde wijzigingen er als volgt uit: