La plupart des modules complémentaires basés sur des cartes sont créés à l'aide de plusieurs fiches qui représentent différentes "pages" de l'interface du module complémentaire. Pour offrir 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 poussant et en affichant des cartes vers et depuis une seule pile de cartes, la carte supérieure de la pile étant affichée par Gmail.
Les modules complémentaires Google Workspace introduisent les pages d'accueil et les fiches non contextuelles. Pour prendre en charge 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, le homepageTrigger
correspondant se déclenche pour créer la première fiche de page d'accueil de la pile (fiche "page d'accueil" bleu foncé dans le diagramme ci-dessous).
Si aucun homepageTrigger
n'est défini, une fiche par défaut est créée, affichée et ajouté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 insérer dans la pile (les "cartes transmises" bleues dans le diagramme) lorsque l'utilisateur navigue dans votre module complémentaire. L'interface utilisateur du module complémentaire affiche la fiche supérieure de la pile. Par conséquent, l'ajout de nouvelles fiches à la pile modifie l'affichage, et le retrait de fiches de la pile renvoie l'affichage aux fiches précédentes.
Si votre module complémentaire dispose d'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 la DisplayStyle
de la nouvelle fiche:
- Si
DisplayStyle
estREPLACE
(valeur par défaut), la carte contextuelle (la carte "contextuelle" orange foncé dans le diagramme) remplace la carte actuellement affichée. Cela lance 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
DisplayStyle
estPEEK
, l'UI crée plutôt un en-tête de peek qui s'affiche en bas de la barre latérale du module complémentaire, en superposition de la fiche actuelle. L'en-tête de l'aperçu affiche le titre de la nouvelle fiche et fournit les boutons de commande permettant à l'utilisateur de décider s'il souhaite l'afficher ou non. Si l'utilisateur 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 ajouter à la pile (les "fiches poussées" jaunes 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 élevée. Si l'utilisateur quitte un contexte, les fiches contextuelles de la pile sont supprimées et l'affichage est mis à jour avec la fiche ou la page d'accueil non contextuelle la plus élevée.
Si l'utilisateur saisit un contexte pour lequel votre module complémentaire ne définit pas de déclencheur contextuel, aucune nouvelle fiche n'est créée et la fiche actuelle reste affichée.
Les actions Navigation
décrites ci-dessous ne s'appliquent qu'aux fiches du même contexte. Par exemple, popToRoot()
dans une fiche contextuelle ne fait apparaître que toutes les autres fiches contextuelles et n'a aucun impact sur les fiches 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. La classe Navigation
fournit des fonctions permettant d'ajouter et de supprimer des cartes des piles. Pour créer une navigation efficace entre les fiches, vous devez configurer vos widgets pour qu'ils utilisent des actions de navigation. Vous pouvez insérer ou afficher plusieurs fiches simultanément, mais vous ne pouvez pas supprimer la fiche de la page d'accueil initiale qui est d'abord insérée dans la pile lorsque le module complémentaire démarre.
Pour accéder à une nouvelle fiche en réponse à une interaction de l'utilisateur avec un widget, procédez comme suit:
- Créez un objet
Action
et associez-le à une fonction de rappel que vous définissez. - Appelez la fonction de gestionnaire de widget appropriée du widget pour définir le
Action
sur ce widget. - Implémentez la fonction de rappel qui gère 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
Navigation
pour définir le changement de carte. Un seul objetNavigation
peut 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 classeActionResponseBuilder
et de l'objetNavigation
. - Renvoyez l'
ActionResponse
compilé.
- 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 fiche sur la pile actuelle. Pour ce faire, vous devez d'abord créer la fiche dans son intégralité. |
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 fiches racine ne sont pas supprimées. |
Navigation.popToRoot() |
Supprime toutes les cartes de la pile, à l'exception de la carte racine. Réinitialise essentiellement cette pile de cartes. |
Navigation.popToNamedCard(String) |
Retire les fiches de la pile jusqu'à ce qu'il atteigne une fiche portant le nom donné ou la fiche racine de la pile. Vous pouvez attribuer des noms aux cartes à l'aide de la fonction CardBuilder.setName(String) . |
Navigation.updateCard(Card) |
Remplace la fiche actuelle sur place, en actualisant son affichage dans l'UI. |
Bonnes pratiques pour la navigation
Si une interaction ou un événement utilisateur doit entraîner le rendu des 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 nouvelles 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 fiche actuelle (par exemple, en ajoutant une tâche à une liste de tâches), utilisez
updateCard()
. - Si une interaction ou un événement fournit des informations supplémentaires ou invite l'utilisateur à effectuer une autre action (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 dans l'agenda), utilisez
pushCard()
pour afficher la nouvelle page tout en permettant à l'utilisateur de quitter la nouvelle page à l'aide du bouton Retour. - Si une interaction ou un événement modifie l'état d'une fiche précédente (par exemple, en modifiant le titre d'un élément à partir de la vue détaillée), utilisez
popCard()
,popCard()
,pushCard(previous)
etpushCard(current)
pour mettre à jour la fiche précédente et la fiche actuelle.
Actualiser les fiches
Les modules complémentaires Google Workspace permettent aux utilisateurs d'actualiser votre fiche en réexécutant la fonction de déclencheur Apps Script enregistrée dans votre fichier manifeste. Les utilisateurs déclenchent cette actualisation via un élément de menu du module complémentaire:
Cette action est automatiquement ajoutée aux fiches générées par les fonctions de déclencheur 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 fiches
Les fonctions de page d'accueil ou de déclencheur contextuel 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 fiche, elle est ajoutée à la pile non contextuelle ou contextuelle en tant que fiche racine et l'interface utilisateur de l'application hôte l'affiche.
Si le tableau renvoyé inclut plusieurs objets Card
intégrés, l'application hôte affiche plutôt une nouvelle fiche contenant une liste de l'en-tête de chaque fiche. Lorsque l'utilisateur clique sur l'un de ces en-têtes, l'UI affiche la fiche correspondante.
Lorsque l'utilisateur sélectionne une fiche dans la liste, elle est poussée sur la pile actuelle et l'application hôte l'affiche. Le bouton
renvoie l'utilisateur à la liste des en-têtes de carte.Cette disposition de cartes "plates" peut fonctionner correctement 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 demander à vos fonctions de page d'accueil et de déclencheur contextuel de renvoyer un seul objet de carte.
Exemple
Voici un exemple qui montre comment créer plusieurs cartes avec des boutons de navigation qui permettent de passer de l'une à l'autre. Ces cartes peuvent être ajoutées à la pile contextuelle ou non contextuelle en poussant 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();
}