Aller au contenu principal

Components

Interne

Les composants partagés sont définis dans le dossier shared/components voir code

Editable Bloc

Ce composant sert à gérer l'édition de données en tant que bloc de la page de détail d'une ressource.

Après mise à jour avec succès du back-end, il faut mettre à jour le composant pour que les nouvelles valeurs par défaut du formulaire correspondent aux nouvelles valeurs sauvegardées. Si on omet cela, la fonction reset du formulaire appelée lors du clic sur le bouton "Annuler" va réinitialiser le formulaire à sa valeur initiale lors du premier chargement de la page.

this.editableBloc.resetState(this.form.getRawValue());  // ici on utilise form.getRawValue qui est la valeur actuelle du formulaire qui a été envoyé au back-end

Simple

Paginated

Externe

Cdk-Tree

Angular CDK docs

On se base sur le CDK d'Angular pour construire des arborescences dépliables.

Cas 1 : Tous les éléments sont préchargés

Exemple arborescence document manager

  1. Définition d'un type TreeNode contenant les informations des noeuds.
  2. Définition d'une méthode indiquant si un noeud à des enfants (utilisé dans le template).
  3. Initialisation d'une source de données "dataSource" (passée au cdk-tree).
  4. Initialisation d'un TreeControl permettant au cdk de manipuler les noeuds.
  5. Définition du template
<cdk-tree [dataSource]="dataSource" [treeControl]="treeControl">
<!-- template d'un noeud terminal "sans enfant" -->
<cdk-nested-tree-node
*cdkTreeNodeDef="let node"
class="tree-node"
[ngClass]="{
'active-node': isNodeActive(node),
'hover-node': node.hover
}"
(click)="activateNode(node)"
(mouseover)="node.hover = true"
(mouseout)="node.hover = false"
>
{{ node.name }}
</cdk-nested-tree-node>
<!-- template d'un noeud avec enfant dépliable/repliable -->
<!-- hasChild est la méthode indiquant si un noeud a des enfants -->
<cdk-nested-tree-node
*cdkTreeNodeDef="let node; when: hasChild"
class="tree-node"
[ngClass]="{
'hover-node': node.hover
}"
(mouseover)="node.hover = true"
(mouseout)="node.hover = false"
>
<button
[attr.aria-label]="'Toggle ' + node.name"
cdkTreeNodeToggle
class="btn p-0 text-start"
>
<fa-icon
[icon]="treeControl.isExpanded(node) ? icons.fold : icons.unfold"
></fa-icon>
{{ node.name }}
</button>
<div [class.d-none]="!treeControl.isExpanded(node)">
<!-- container des noeuds enfant (géré par le cdk tree) -->
<ng-container cdkTreeNodeOutlet></ng-container>
</div>
</cdk-nested-tree-node>
</cdk-tree>
attention

Lors d'un rechargement dynamique d'élément de cette arborescence et notamment lors de la suppression de certain noeud, il faut s'assurer de passer au TreeControl une fonction trackBy en configuration qui permet de gérer l'identité d'un noeud. Si on l'omet : les éléments supprimés resteront affichés.

   treeControl = new NestedTreeControl<DocumentTreeNode, string>(
(node) => node.children,
{
trackBy: trackByFn, // (node: TreeNode) => string
},
);

En revanche il ne faut pas passer de propriété trackBy au composant cdk-tree, un problème d'implémentation empêche la suppression des noeuds (see issue)

Cas 2 : On charge les enfants d'un noeud dynamiquement

Exemple arborescence structures

Afin de réfleter les ajouts de noeuds il est important d'utiliser un Observable pour mettre à jour les enfants et s'assurer que le tree "voit" les mises à jour, ici on utilise un BehaviorSubject.

export interface StructureTreeNode {
id: number;
intitule: string;
children: BehaviorSubject<StructureTreeNode[]>;
loading = false;
}

On écoute dynamiquement les actions de pliage/dépliage des noeuds qui sont executés par la directive CdkTreeNodeToggle pour charger les enfants.

this.treeControl.expansionModel.changed.subscribe((change) => {
//change.added = expanding node / change.removed = collapsing node
if (change.added) {
// change.added is a list to handle case where multiple nodes are affected at the same time
change.added.forEach((node) => this.loadChildren(node));
}
}),
astuce

Il est déconseillé d'ajouter la configuration trackBy au TreeControl dans ce cas car cela change la nature des évènements de changement, ils n'émettent plus des noeuds mais des id correspondant au retour de la méthode trackBy, ce qui implique de recherche le noeud dans le dataSource pour mettre à jour les enfants.

treeControl = new NestedTreeControl<StructureTreeNode, number>(
(node) => node.children,
{
trackBy: (node) => node.id, //return a number
},
);

this.treeControl.expansionModel.changed.subscribe((change) => {
// change is automatically typed as SelectionChange<number>, the param node is now a number
change.added.forEach((node) => this.loadChildren(node));
}),

Stepper

Angular CDK docs

On se base sur le CDK d'Angular pour construire des formulaires sur plusieurs étapes.

Example file uploader

//TODO: complete docs