Passer au contenu principal

Integrating an App Layout

Ouvrir dans ChatGPT

Dans cette étape, vous allez rassembler toutes les parties de votre application dans une mise en page cohérente. À la fin de cette étape, la structure de votre application ressemblera étroitement à l'archétype SideMenu, et vous aurez une meilleure compréhension de la façon dont les composants et concepts suivants fonctionnent :

Exécution de l'application

Au fur et à mesure que vous développez votre application, vous pouvez utiliser 6-integrating-an-app-layout comme point de comparaison. Pour voir l'application en action :

  1. Naviguez vers le répertoire de niveau supérieur contenant le fichier pom.xml, c'est 6-integrating-an-app-layout si vous suivez la version sur GitHub.

  2. Utilisez la commande Maven suivante pour exécuter l'application Spring Boot localement :

    mvn

L'exécution de l'application ouvre automatiquement un nouveau navigateur à http://localhost:8080.

Création d'un composant réutilisable

Dans une étape précédente, Routing and Composites, vous avez créé deux composants composites qui contenaient le contenu de la table des clients et du formulaire client. Dans le cadre de cette étape, vous allez créer un composant composite plus petit et réutilisable pour afficher le nom de l'application à l'intérieur du menu latéral et une page à propos. Si vous décidez de changer le nom de l'application à l'avenir, vous n'aurez qu'à le mettre à jour dans ce composant.

Dans src/main/java/com/webforj/tutorial/components, créez une classe appelée AppTitle. Le composant lié pour AppTitle sera un FlexLayout, un composant conteneur qui est utilisé tout au long de cette étape pour vous montrer comment créer des mises en page plus complexes. Pour ce FlexLayout, vous allez arranger la direction des éléments et l'espacement entre les éléments. Cela se fait en utilisant les méthodes setDirection() et setSpacing() respectivement.

AppTitle.java
// Faire du composant lié un FlexLayout
public class AppTitle extends Composite<FlexLayout> {
private FlexLayout self = getBoundComponent();

public AppTitle() {

// Disposer les éléments verticalement
self.setDirection(FlexDirection.COLUMN);

// Définir l'écart entre les éléments
self.setSpacing("0px");
}
}

Ensuite, utilisez des éléments HTML standard pour créer le titre et le sous-titre. Définir la marge inférieure d'un élément d'en-tête à 0px rapproche les éléments, et vous pouvez styliser le sous-titre en utilisant les variables CSS DWC.

AppTitle.java
public class AppTitle extends Composite<FlexLayout> {
private FlexLayout self = getBoundComponent();
private H2 title = new H2("Gestionnaire de Clients");
private Paragraph subTitle = new Paragraph("Un Système d'Enregistrement Simple");

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);
}
}

Rendu optionnel

Bien que AppTitle soit simple, ajouter un argument booléen au constructeur permet de contrôler quand afficher certaines parties du composant, comme le sous-titre.

AppTitle.java
// Ajouter un argument booléen
public AppTitle(boolean showSubTitle) {

self.setDirection(FlexDirection.COLUMN)
.setSpacing("0px")

// Ajouter le titre par défaut
.add(title);

// Afficher éventuellement le sous-titre
if (showSubTitle) {
self.add(subTitle);
}
}

AppTitle terminé

Dans l'ensemble, le composant réutilisable devrait ressembler à ceci :

AppTitle.java
public class AppTitle extends Composite<FlexLayout> {
private FlexLayout self = getBoundComponent();
private H2 title = new H2("Gestionnaire de Clients");
private Paragraph subTitle = new Paragraph("Un Système d'Enregistrement Simple");

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);
}
}
}

Création d'une page à propos

Le premier endroit où ajouter le composant AppTitle nouvellement créé sera une page à propos. Cette page comprend une image et le composant AppTitle, centré sur la page en utilisant un autre FlexLayout.

Centrer le contenu à l'aide d'un FlexLayout

L'objectif est de centrer le contenu de la page à propos en utilisant le FlexLayout. Le composant FlexLayout suit le modèle de mise en page flexbox CSS. Les méthodes pour le FlexLayout, comme celles utilisées précédemment pour orienter les éléments en colonne, sont différentes façons d'arranger les éléments.

Les méthodes pour arranger les éléments dans un FlexLayout utilisent un système de direction relatif. Au lieu de penser aux axes horizontal et vertical, il est préférable de penser à l'axe parallèle aux éléments comme à l'axe principal, et à l'axe perpendiculaire aux éléments comme à l'axe transversal.

Définir les propriétés FlexJustifyContent et FlexAlignment sur CENTER centrera les éléments le long des axes principal et transversal dans le FlexLayout, et faire en sorte que le FlexLayout prenne toute la taille de son conteneur parent le rend centré sur la page.

private final FlexLayout layout = new FlexLayout();

// Remplir tout l'espace de l'élément parent
layout.setSize("100%", "100%");

// Rendre l'axe principal vertical
layout.setDirection(FlexDirection.COLUMN);

// Centrer les éléments le long de l'axe transversal
layout.setAlignment(FlexAlignment.CENTER);

// Centrer les éléments le long de l'axe principal
layout.setJustifyContent(FlexJustifyContent.CENTER);

Pour aider à visualiser comment les différentes méthodes fonctionnent, consultez l'article de blog FlexWrap votre esprit autour de FlexLayout de webforJ.

Ajout de ressources

Un des éléments qui ira à l'intérieur du FlexLayout centré est une image. Pour ce tutoriel, vous pouvez visualiser et télécharger l'image de la page à propos sur GitHub. Une fois téléchargée, ajoutez-la au dossier statique de votre projet dans src/main/resources/static/images et nommez-la Files.svg.

Placer cette image dans le dossier statique vous permet de la référencer en utilisant le protocole Webserver, comme vous l'avez fait lorsque vous avez référencé le fichier CSS dans la première étape, Création d'une Application Basique. Ensuite, vous pouvez l'utiliser à l'intérieur de votre application en tant qu'élément HTML, comme ceci :

private Img fileImg = new Img("ws://images/Files.svg");

Création de AboutView

Comme les deux pages d'application existantes, la page à propos sera une vue routable. Dans src/main/java/com/webforj/tutorial/views, ajoutez une classe nommée AboutView. Utilisez un FlexLayout pour le composant lié, comme vous l'avez fait pour AppTitle.

Puisque vous avez nommé la classe AboutView, il n'est pas nécessaire de donner une valeur personnalisée pour le mappage d'URL ; cette page se rend par défaut à http://localhost:8080/about.

Voici à quoi cela ressemble lorsque vous utilisez les concepts des étapes précédentes avec les composants nouvellement créés pour créer une nouvelle vue avec un contenu centré :

AboutView.java
@Route()
@FrameTitle("À propos")
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));
}
}

Création de la route Layout

Cela est brièvement mentionné dans l'étape Routing and Composites, mais il existe deux types de routes. MainView, FormView et AboutView sont toutes des routes View, tandis que le type de route que vous utiliserez pour créer le menu latéral de l'application est une route Layout.

Les routes de mise en page enveloppent les vues enfants et permettent à certaines parties de l'interface utilisateur de persister entre les vues, comme un menu latéral. Dans src/main/java/com/webforj/tutorial/layouts, créez une classe appelée MainLayout.

Route outlets

Comme les routes de vue, MainLayout a besoin d'une annotation @Route. Cependant, parce qu'elle a Layout comme suffixe et que les routes de mise en page ne contribuent pas à l'URL, cette annotation n'a pas besoin d'arguments.

MainLayout.java
@Route
public class MainLayout {

public MainLayout() {

}
}

L'application sait quelles vues rendre à l'intérieur de MainLayout en déclarant la classe de mise en page comme le route outlet dans chaque vue. Les étapes précédentes contenaient seulement une propriété value définie dans les annotations @Route, donc maintenant vous devrez indiquer explicitement quelles sont les propriétés value et outlet pour les classes de vue.

@Route(value = "/", outlet = MainLayout.class)
Final touches

C'est la dernière modification requise pour FormView et AboutView dans cette étape, donc n'oubliez pas de mettre à jour l'annotation @Route pour ces vues avant d'exécuter votre application.

Utilisation du composant AppLayout

Maintenant que votre application rend les vues à l'intérieur de MainLayout, vous pouvez choisir où ces composants se rendent. Choisir l'AppLayout comme composant lié pour MainLayout vous permet de stocker les vues dans une zone de contenu principal par défaut, tout en vous offrant différentes zones pour ajouter des éléments pour l'en-tête et le menu latéral.

Slots

Pour de nombreux conteneurs webforJ, l'utilisation des méthodes add() ajoute des composants de l'interface utilisateur à la zone de contenu principal. Dans le composant AppLayout, il existe plusieurs zones pour ajouter des composants de l'interface utilisateur, chacune dans un slot séparé. En marquant MainLayout comme une route de mise en page et en définissant son composant lié comme un AppLayout, les vues se rendent automatiquement dans le slot de contenu principal.

Dans cette étape, vous utiliserez les slots drawer-title et drawer pour créer un menu latéral, et le slot header pour afficher quelle page l'utilisateur se trouve et un basculement pour le menu latéral.

Création d'un menu latéral

Lorsqu'il y a suffisamment de place à l'écran sur l'appareil, le composant AppLayout affiche un tiroir. C'est là que vous ajouterez à nouveau l'AppTitle et les éléments qui permettront aux utilisateurs de naviguer dans l'application.

Par défaut, AppLayout ne montre pas d'en-tête de tiroir, mais en utilisant la méthode setDrawerHeaderVisible(), vous pouvez afficher les éléments qui se trouvent dans le slot drawer-title, qui sera l'AppTitle avec son sous-titre affiché.

private AppLayout appLayout = new AppLayout();

// Montrer l'en-tête du tiroir
appLayout.setDrawerHeaderVisible(true);

// Ajouter l'AppTitle à l'en-tête du tiroir avec son sous-titre
appLayout.addToDrawerTitle(new AppTitle(true));

Le slot drawer devrait ensuite contenir les composants qui permettront aux utilisateurs de naviguer dans l'application. L'utilisation du composant AppNav facilite la création de nouvelles options de navigation. Pour chaque lien, vous devez simplement créer un AppNavItem. Les composants AppNavItem dans ce tutoriel utilisent trois paramètres :

  • L'étiquette pour le lien
  • La vue cible
  • Un composant Icon facultatif, utilisant des images de Tabler

Regrouper tous les paramètres du tiroir dans MainLayout ressemble à ceci :

MainLayout
@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("Tableau de Bord", MainView.class,
TablerIcon.create("archive")));
appNav.addItem(new AppNavItem("À propos", AboutView.class,
TablerIcon.create("info-circle")));
self.addToDrawer(appNav);
}
}

Création d'un en-tête

Le slot header doit inclure deux éléments : un basculement pour montrer ou cacher le menu latéral et un moyen d'afficher le titre du cadre. Ces deux éléments seront à l'intérieur d'un composant Toolbar, une autre façon d'organiser les composants.

Vous pouvez inclure le basculement pour le tiroir AppLayout avec le composant AppDrawerToggle. Ce composant est déjà stylisé avec une icône couramment utilisée pour les options de menu cachées, et cible le tiroir pour l'ouvrir et le fermer.

// Créer les composants conteneurs
private AppLayout appLayout = new AppLayout();
private Toolbar toolbar = new Toolbar();

// Ajouter la Toolbar à l'en-tête de l'AppLayout
appLayout.addToHeader(toolbar);

// Ajouter l'AppDrawerToggle à la barre d'outils
toolbar.addToStart(new AppDrawerToggle());

L'en-tête peut également afficher le titre du cadre en utilisant l'événement de navigation pour récupérer des détails sur le composant entrant, tout en ayant un écouteur d'événement pour supprimer l'enregistrement afin de prévenir les fuites de mémoire.

// Créer l'élément H1 et l'enregistrement de navigation
private H1 title = new H1("");
private ListenerRegistration<NavigateEvent> navigateRegistration;

// Enregistrer l'événement lors de la navigation
navigateRegistration = Router.getCurrent().onNavigate(this::onNavigate);

// Supprimer les écouteurs avant que MainLayout ne soit détruit
@Override
protected void onDidDestroy() {
if (navigateRegistration != null) {
navigateRegistration.remove();
}
}

// Récupérer le titre du cadre de la classe de vue entrante
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() : "");
}
}

MainLayout terminé

Voici MainLayout avec le contenu créé pour le tiroir et l'en-tête à l'intérieur d'un AppLayout :

MainLayout.java
@Route
public class MainLayout extends Composite<AppLayout> {
private AppLayout self = getBoundComponent();
private H1 title = new H1("");
private ListenerRegistration<NavigateEvent> navigateRegistration;
private Toolbar toolbar = new Toolbar();
private AppNav appNav = new AppNav();

public MainLayout() {
setHeader();
setDrawer();
navigateRegistration = Router.getCurrent().onNavigate(this::onNavigate);
}

private void setHeader() {
self.addToHeader(toolbar);

toolbar.addToStart(new AppDrawerToggle());
toolbar.addToTitle(title);
}

Mise à jour de FormView

Comme mentionné précédemment, le seul changement apporté à FormView était l'annotation @Route.

@Route(value = "customer/:id?<[0-9]+>", outlet = MainLayout.class)

Mise à jour de MainView

Pour MainView, vous changerez le composant lié d'un Div à un FlexLayout. Cela vous permet de centrer le tableau, tout en déplaçant des composants spécifiques à l'intérieur de la mise en page. Utiliser la méthode setItemAlignment() vous permet de choisir un composant dans la mise en page et de le déplacer, donc vous pouvez garder le tableau centré tout en ancrant le bouton d'ajout de client en haut à droite de la mise en page.

// Changer le composant lié en un FlexLayout
private FlexLayout self = getBoundComponent();

// Aligner le bouton à la fin de l'axe transversal
self.setItemAlignment(FlexAlignment.END, addCustomer);

Une autre amélioration que vous pouvez apporter ici est la largeur du tableau. Au lieu d'une largeur fixe, vous pouvez la définir pour qu'elle corresponde à son conteneur parent, le FlexLayout. Ensuite, ce FlexLayout peut avoir une largeur maximale pour ne pas s'étirer excessivement sur des écrans plus grands.

private FlexLayout self = getBoundComponent();
private Table<Customer> table = new Table<>();

self.setSize("100%", "100%");
self.setMaxWidth(2000);

table.setSize("100%", "294px");

En combinant ces éléments et en créant une autre méthode pour centrer le FlexLayout, vous obtenez MainView avec les modifications mises en avant :

MainView.java
@Route(value = "/", outlet = MainLayout.class)
@FrameTitle("Tableau des Clients")
public class MainView extends Composite<FlexLayout> {
private final CustomerService customerService;
private FlexLayout self = getBoundComponent();
private Table<Customer> table = new Table<>();
private Button addCustomer = new Button("Ajouter un Client", ButtonTheme.PRIMARY,
e -> Router.getCurrent().navigate(FormView.class));

public MainView(CustomerService customerService) {
this.customerService = customerService;
addCustomer.setWidth(200);
buildTable();
setFlexLayout();
self.add(addCustomer, table);