La plupart des modules complémentaires basés sur des fiches sont conçus à l'aide de plusieurs fiches qui représentent différentes "pages" de l'interface du module complémentaire. Pour une expérience utilisateur efficace, vous devez utiliser une navigation simple et naturelle entre les fiches de votre module complémentaire.
À l'origine, dans les modules complémentaires Gmail, les transitions entre les différentes cartes de l'UI sont gérées en ajoutant et en supprimant des cartes dans une pile unique, la carte du dessus étant affichée par Gmail.

Les modules complémentaires Google Workspace introduisent les pages d'accueil et les fiches non contextuelles. Pour gérer les cartes contextuelles et non contextuelles, les modules complémentaires Google Workspace disposent d'une pile de cartes interne pour chacune d'elles. Lorsqu'un module complémentaire est ouvert dans un hôte, l'homepageTrigger correspondant se déclenche pour créer la première fiche de page d'accueil dans la pile (la fiche bleue foncée "page d'accueil" dans le diagramme ci-dessous).
Si aucun homepageTrigger n'est défini, une fiche par défaut est créée, affichée et envoyée à la pile non contextuelle. Cette première carte est une carte racine.
Votre module complémentaire peut créer des cartes non contextuelles supplémentaires et les empiler (les cartes bleues "pushed cards" dans le diagramme) à mesure que l'utilisateur navigue dans votre module complémentaire. L'UI du module complémentaire affiche la carte supérieure de la pile. Par conséquent, l'ajout de nouvelles cartes à la pile modifie l'affichage, et la suppression de cartes de la pile renvoie l'affichage aux cartes précédentes.
Si votre module complémentaire comporte un déclencheur contextuel défini, le déclencheur se déclenche lorsque l'utilisateur entre dans ce contexte. La fonction de déclencheur crée la fiche contextuelle, mais l'affichage de l'UI est mis à jour en fonction de l'DisplayStyle de la nouvelle fiche :
- Si
DisplayStyleest défini surREPLACE(valeur par défaut), la fiche contextuelle (la fiche "contextuelle" orange foncé dans le diagramme) remplace la fiche actuellement affichée. Cela démarre effectivement une nouvelle pile de cartes contextuelles au-dessus de la pile de cartes non contextuelles. Cette carte contextuelle est la carte racine de la pile contextuelle. - Si
DisplayStyleest défini surPEEK, l'UI crée un en-tête de prévisualisation qui s'affiche en bas de la barre latérale du module complémentaire, en superposition de la carte actuelle. L'en-tête de l'aperçu affiche le titre de la nouvelle fiche et fournit les commandes de bouton permettant à l'utilisateur de décider s'il souhaite afficher la nouvelle fiche ou non. S'il clique sur le bouton Afficher, la fiche remplace la fiche actuelle (comme décrit ci-dessus avecREPLACE).
Vous pouvez créer des fiches contextuelles supplémentaires et les envoyer dans la pile (les fiches jaunes "pushed cards" dans le diagramme). La mise à jour de la pile de cartes modifie l'interface utilisateur du module complémentaire pour afficher la carte la plus haute. Si l'utilisateur quitte un contexte, les cartes contextuelles de la pile sont supprimées et l'affichage est mis à jour pour afficher la carte non contextuelle la plus haute ou la page d'accueil.
Si l'utilisateur saisit un contexte pour lequel votre module complémentaire ne définit pas de déclencheur contextuel, aucune carte n'est créée et la carte actuelle reste affichée.
Les actions Navigation décrites ci-dessous n'agissent que sur les cartes du même contexte. Par exemple, popToRoot() à partir d'une carte contextuelle ne ferme que toutes les autres cartes contextuelles et n'affecte pas les cartes de la page d'accueil.
En revanche, le bouton est toujours disponible pour permettre à l'utilisateur de passer de vos fiches contextuelles à vos fiches non contextuelles.
Méthodes de navigation
Vous pouvez créer des transitions entre les fiches en ajoutant ou en supprimant des fiches des piles de fiches. La classe Navigation fournit des fonctions permettant d'ajouter et de supprimer des cartes des piles. Pour créer une navigation par carte efficace, configurez vos widgets afin qu'ils utilisent des actions de navigation. Vous pouvez pousser ou retirer plusieurs cartes simultanément, mais vous ne pouvez pas supprimer la carte de page d'accueil initiale qui est poussée en premier dans la pile lorsque le module complémentaire démarre.
Pour accéder à une nouvelle fiche en réponse à une interaction utilisateur avec un widget, procédez comme suit :
- Créez un objet
Actionet associez-le à une fonction de rappel que vous définissez. - Appelez la fonction de gestionnaire de widget appropriée du widget pour définir
Actionsur ce widget. - Implémentez la fonction de rappel qui effectue la navigation. Cette fonction reçoit un objet d'événement d'action comme argument et doit effectuer les opérations suivantes :
- Créez un objet
Navigationpour définir le changement de carte. Un seul objetNavigationpeut contenir plusieurs étapes de navigation, qui sont effectuées dans l'ordre dans lequel elles sont ajoutées à l'objet. - Créez un objet
ActionResponseà l'aide de la classeActionResponseBuilderet de l'objetNavigation. - Renvoie le
ActionResponsecréé.
- Créez un objet
Lorsque vous créez des commandes de navigation, vous utilisez les fonctions d'objet Navigation suivantes :
| Fonction | Description |
|---|---|
Navigation.pushCard(Card) |
Transfère une carte sur la pile actuelle. Pour cela, vous devez d'abord créer la fiche entièrement. |
Navigation.popCard() |
Supprime une carte du haut de la pile. Équivaut à cliquer sur la flèche de retour dans la ligne d'en-tête du module complémentaire. Les cartes racines ne sont pas supprimées. |
Navigation.popToRoot() |
Supprime toutes les cartes de la pile, à l'exception de la carte racine. Cela réinitialise essentiellement la pile de cartes. |
Navigation.popToNamedCard(String) |
Supprime les cartes de la pile jusqu'à ce qu'elle atteigne une carte portant le nom donné ou la carte racine de la pile. Vous pouvez attribuer des noms aux cartes à l'aide de la fonction CardBuilder.setName(String). |
Navigation.updateCard(Card) |
Remplace la carte actuelle sur place et actualise son affichage dans l'UI. |
Bonnes pratiques de navigation
Si une interaction ou un événement utilisateur doit entraîner le rendu de cartes dans le même contexte, utilisez les méthodes Navigation.pushCard(), Navigation.popCard() et Navigation.updateCard() pour remplacer les cartes existantes. Si une interaction ou un événement utilisateur doit entraîner le rendu de cartes dans un contexte différent, utilisez ActionResponseBuilder.setStateChanged() pour forcer la réexécution de votre module complémentaire dans ces contextes.
Voici des exemples de navigation :
- Si une interaction ou un événement modifie l'état de la carte actuelle (par exemple, l'ajout d'une tâche à une liste de tâches), utilisez
updateCard(). - Si une interaction ou un événement fournit plus de détails ou invite l'utilisateur à effectuer une action supplémentaire (par exemple, cliquer sur le titre d'un élément pour en savoir plus ou appuyer sur un bouton pour créer un événement d'agenda), utilisez
pushCard()pour afficher la nouvelle page tout en permettant à l'utilisateur de la quitter à l'aide du bouton Retour. - Si une interaction ou un événement met à jour l'état d'une carte précédente (par exemple, en modifiant le titre d'un élément dans la vue détaillée), utilisez des éléments tels que
popCard(),popCard(),pushCard(previous)etpushCard(current)pour mettre à jour la carte précédente et la carte actuelle.
Actualiser les fiches
Les modules complémentaires Google Workspace permettent aux utilisateurs d'actualiser votre fiche en exécutant à nouveau la fonction de déclencheur Apps Script enregistrée dans votre fichier manifeste. Les utilisateurs déclenchent cette actualisation à l'aide d'un élément de menu de module complémentaire :
Cette action est automatiquement ajoutée aux fiches générées par les fonctions de déclenchement homepageTrigger ou contextualTrigger, comme spécifié dans le fichier manifeste de votre module complémentaire (les "racines" des piles de fiches contextuelles et non contextuelles).
Renvoyer plusieurs cartes
Les fonctions de déclenchement contextuel ou de page d'accueil permettent de créer et de renvoyer un seul objet Card ou un tableau d'objets Card que l'UI de l'application affiche.
S'il n'y a qu'une seule carte, elle est ajoutée à la pile non contextuelle ou contextuelle en tant que carte racine, et l'UI de l'application hôte l'affiche.
Si le tableau renvoyé inclut plusieurs objets Card intégrés, l'application hôte affiche une nouvelle fiche contenant la liste des en-têtes de chaque fiche. Lorsque l'utilisateur clique sur l'un de ces en-têtes, l'UI affiche la carte correspondante.
Lorsque l'utilisateur sélectionne une carte dans la liste, celle-ci est ajoutée à la pile actuelle et l'application hôte l'affiche. Le bouton permet à l'utilisateur de revenir à la liste des en-têtes de carte.
Cette disposition de cartes "plates" peut être utile si votre module complémentaire n'a pas besoin de transitions entre les cartes que vous créez. Toutefois, dans la plupart des cas, il est préférable de définir directement les transitions de carte et de faire en sorte que vos fonctions de déclenchement contextuel et de page d'accueil renvoient un seul objet de carte.
Exemple
Voici un exemple qui montre comment construire plusieurs cartes avec des boutons de navigation permettant de passer de l'une à l'autre. Ces cartes peuvent être ajoutées à la pile contextuelle ou non contextuelle en insérant la carte renvoyée par createNavigationCard() dans ou en dehors d'un contexte particulier.
/**
* Create the top-level card, with buttons leading to each of three
* 'children' cards, as well as buttons to backtrack and return to the
* root card of the stack.
* @return {Card}
*/
function createNavigationCard() {
// Create a button set with actions to navigate to 3 different
// 'children' cards.
var buttonSet = CardService.newButtonSet();
for(var i = 1; i <= 3; i++) {
buttonSet.addButton(createToCardButton(i));
}
// Build the card with all the buttons (two rows)
var card = CardService.newCardBuilder()
.setHeader(CardService.newCardHeader().setTitle('Navigation'))
.addSection(CardService.newCardSection()
.addWidget(buttonSet)
.addWidget(buildPreviousAndRootButtonSet()));
return card.build();
}
/**
* Create a button that navigates to the specified child card.
* @return {TextButton}
*/
function createToCardButton(id) {
var action = CardService.newAction()
.setFunctionName('gotoChildCard')
.setParameters({'id': id.toString()});
var button = CardService.newTextButton()
.setText('Card ' + id)
.setOnClickAction(action);
return button;
}
/**
* Create a ButtonSet with two buttons: one that backtracks to the
* last card and another that returns to the original (root) card.
* @return {ButtonSet}
*/
function buildPreviousAndRootButtonSet() {
var previousButton = CardService.newTextButton()
.setText('Back')
.setOnClickAction(CardService.newAction()
.setFunctionName('gotoPreviousCard'));
var toRootButton = CardService.newTextButton()
.setText('To Root')
.setOnClickAction(CardService.newAction()
.setFunctionName('gotoRootCard'));
// Return a new ButtonSet containing these two buttons.
return CardService.newButtonSet()
.addButton(previousButton)
.addButton(toRootButton);
}
/**
* Create a child card, with buttons leading to each of the other
* child cards, and then navigate to it.
* @param {Object} e object containing the id of the card to build.
* @return {ActionResponse}
*/
function gotoChildCard(e) {
var id = parseInt(e.parameters.id); // Current card ID
var id2 = (id==3) ? 1 : id + 1; // 2nd card ID
var id3 = (id==1) ? 3 : id - 1; // 3rd card ID
var title = 'CARD ' + id;
// Create buttons that go to the other two child cards.
var buttonSet = CardService.newButtonSet()
.addButton(createToCardButton(id2))
.addButton(createToCardButton(id3));
// Build the child card.
var card = CardService.newCardBuilder()
.setHeader(CardService.newCardHeader().setTitle(title))
.addSection(CardService.newCardSection()
.addWidget(buttonSet)
.addWidget(buildPreviousAndRootButtonSet()))
.build();
// Create a Navigation object to push the card onto the stack.
// Return a built ActionResponse that uses the navigation object.
var nav = CardService.newNavigation().pushCard(card);
return CardService.newActionResponseBuilder()
.setNavigation(nav)
.build();
}
/**
* Pop a card from the stack.
* @return {ActionResponse}
*/
function gotoPreviousCard() {
var nav = CardService.newNavigation().popCard();
return CardService.newActionResponseBuilder()
.setNavigation(nav)
.build();
}
/**
* Return to the initial add-on card.
* @return {ActionResponse}
*/
function gotoRootCard() {
var nav = CardService.newNavigation().popToRoot();
return CardService.newActionResponseBuilder()
.setNavigation(nav)
.build();
}