| name | angular-rules |
| description | Règles partagées Angular pour la toolbox Soliguide. À utiliser dès qu'on code un composant, un formulaire, une page, une modale, ou que l'utilisateur dit "ajoute un formulaire", "fais une page Angular", "modale", "validation", "accessibilité Angular", "RGAA". Documente la convention Reactive Forms obligatoire + le checklist RGAA appliqué aux formulaires. |
Règles Angular Soliguide
Conventions partagées pour tous les composants Angular écrits dans la toolbox. Toujours répondre en français. Tutoyer l'utilisateur.
1. Formulaires : Reactive Forms par défaut
Tous les formulaires sont des ReactiveForms. Pas de [(ngModel)] ni de signal manuellement câblé avec (input). Raison : typage strict, validation déclarative, intégration Enter → submit propre, testabilité.
Pattern à suivre
import { Component } from "@angular/core";
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from "@angular/forms";
@Component({
selector: "app-ma-modale",
imports: [ReactiveFormsModule],
templateUrl: "./ma-modale.html",
})
export class MaModale {
protected readonly form = new FormGroup({
content: new FormControl("", {
nonNullable: true,
validators: [Validators.required, Validators.minLength(1)],
}),
username: new FormControl("", {
nonNullable: true,
validators: [Validators.required, Validators.maxLength(128)],
}),
});
protected submit(): void {
if (this.form.invalid) {
this.form.markAllAsTouched();
return;
}
const { content, username } = this.form.getRawValue();
}
}
<form [formGroup]="form" (ngSubmit)="submit()">
…
<button type="submit">Confirmer</button>
</form>
Règles non-négociables
FormControl typés et nonNullable: true pour ne pas porter null partout.
- Validators déclarés dans le composant, pas dans le template.
- Bouton submit :
type="submit". Tous les autres boutons du form : type="button" explicite (sinon le browser les considère comme submit et Enter les déclenche).
(ngSubmit) sur le <form>, pas (click) sur le bouton submit. C'est ngSubmit qui assure Enter → submit.
2. RGAA : accessibilité obligatoire sur tous les formulaires
Tous les formulaires de la toolbox sont conformes au RGAA (Référentiel Général d'Amélioration de l'Accessibilité). Checklist appliquée systématiquement :
Labels
Clavier
- Espace et Entrée sur un bouton focus doivent déclencher l'action. Toujours utiliser
<button type="…">, jamais <div role="button">.
- Enter dans un input texte d'un formulaire doit déclencher le submit. Garanti par
(ngSubmit) + <button type="submit">.
- Enter dans un
<textarea> reste un saut de ligne (comportement natif, attendu).
- Pour les dropdowns DaisyUI : le trigger doit être un
<button>. Le menu s'ouvre via :focus-within (CSS pur).
Erreurs
- Toujours afficher les erreurs en rouge avec une classe DaisyUI :
text-error, alert alert-error alert-soft.
- Erreurs de validation par champ : affichées sous le champ quand
controls.X.touched && controls.X.errors.
- Erreur API globale :
alert alert-error alert-soft dans la modale.
<input formControlName="username" />
@if (form.controls.username.touched && form.controls.username.errors) {
<span class="text-error text-xs mt-1">Pseudo requis.</span>
}
Aria
- Si un champ n'a vraiment pas pu avoir de
<label> visible (cas exceptionnel), aria-label minimum.
<dialog> natif HTML pour les modales (DaisyUI class="modal"), pas de <div role="dialog">. Le natif gère focus trap + Esc.
3. CSS / Style
- Aucun CSS custom. Utiliser uniquement les classes DaisyUI et Tailwind.
- Les composants DaisyUI à connaître pour les formulaires :
form-control, label, label-text, label-text-alt, input, input-bordered, textarea, textarea-bordered, select, checkbox, radio, btn, alert.
- Tailles :
input-sm / btn-sm quand on est dans une barre dense (header, toolbar). Sinon input-md / btn-md.
4. Composants standalone par défaut
- Composants
standalone: true (défaut Angular 20). Pas de NgModule.
imports: [...] au niveau du @Component. Inclure ReactiveFormsModule quand le template utilise [formGroup] ou formControlName.
- Pour qu'un composant prenne sa largeur naturelle dans un parent inline/flex, déclarer son display via
host: { class: "inline-flex items-center align-middle" } (sinon le défaut Angular est display: inline → enfants block sans largeur).
5. Favicon Soliguide
Dans le public/ du dashboard Angular (servi tel quel par Angular CLI à la racine), toujours utiliser le favicon partagé :
cp assets/images/icons/favicon.ico projects/<nom>/apps/dashboard/public/favicon.ico
Le fichier source est assets/images/icons/favicon.ico (Solinum officiel — set complet PWA dispo dans le même dossier : favicon-16x16.png, favicon-32x32.png, apple-icon-*.png, manifest.json).
Dans le <head> du src/index.html :
<link rel="icon" type="image/x-icon" href="favicon.ico" />
Ne jamais garder le favicon par défaut généré par ng new — c'est la base de cohérence visuelle avec les autres outils Soliguide.
6. Modales
<dialog> natif HTML stylé avec class="modal" DaisyUI.
- Ouverture / fermeture via
dialog().nativeElement.showModal() / .close() (viewChild typé ElementRef<HTMLDialogElement>).
- Backdrop :
<form method="dialog" class="modal-backdrop"> natif, ferme au clic dehors.
- Form principal :
<form [formGroup]> séparé du backdrop. Ne pas mélanger les deux.
En résumé
Un formulaire correct dans la toolbox :
✅ Reactive Form (FormGroup + FormControl typés)
✅ <form [formGroup] (ngSubmit)> + bouton submit type="submit"
✅ Autres boutons du form : type="button" explicite
✅ Chaque champ : <label> visible (form-control DaisyUI)
✅ Erreurs par champ : text-error sous l'input
✅ Erreur globale : alert alert-error alert-soft
✅ Modale : <dialog> natif + backdrop séparé
✅ Pas de CSS custom, uniquement DaisyUI / Tailwind
✅ Pas de [(ngModel)], pas de <div role="button">