Skip to content

Commit

Permalink
Update Form chapter practical work
Browse files Browse the repository at this point in the history
  • Loading branch information
Ocunidee committed Feb 12, 2025
1 parent 782efcd commit b754e93
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 21 deletions.
37 changes: 27 additions & 10 deletions docs/src/forms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ The following component shows an example of how to take advantage of:
You can find an updated list of classes [here](https://angular.io/guide/form-validation#control-status-css-classes).

## Practical work: Login and registration with reactive forms
1. Implement the login / registration form using reactive forms and the form builder: replace the `[(ngModel)]` in the template and delete the `email` and `password` from the class of the `LoginFormComponent`.
1. Implement the login / registration form using reactive forms and the form builder: replace the `[(ngModel)]` in the template and delete the `email` and `password` from the class of the `LoginFormComponent`, declare a `FormGroup` named `loginForm`.

2. Add the required validator (`Validators.required`) to both email and password fields. Show the text `"This field is required"` under each field if the form is dirty and that field has the error `required`:

Expand All @@ -145,29 +145,45 @@ You can find an updated list of classes [here](https://angular.io/guide/form-val
```

::: tip Hint
- You can get a specific form control using the `get('form control name')` method of a form group.
- You can check if a form control has a specific error by using the `hasError('error name')` method of form controls.
- You can get access to a specific `FormControl` instance using the `controls` property of the `FormGroup` containing it. For exemple for a `FormGroup` named *myFormGroup* and a `FormControl` named *myControl*:
```ts
myFormGroup.controls.myControl.touched
```
- You can check if a `FormControl` (more generally an `AbstractControl`) has a specific error by using the `hasError('error name')` method of the `FormControl` class. For exemple for a `FormGroup` named *myFormGroup*, a `FormControl` named *myControl* and an error *required*:
```ts
myFormGroup.controls.myControl.hasError('required')
```
:::

3. Style the label and error text of each field with the `.ng-invalid` class when the form is dirty and that field is invalid (remember the `[class]` attribute). Be careful to target only those two elements (you can use the `+` CSS selector to that purpose).
3. Style the label and error text of each input that has the `.ng-invalid` class applied by angular but only when the form has the `ng-dirty` class. Be careful to target only those two elements (you can use the `+` CSS combinator and the `:has()` pseudo-class to that purpose).

::: details Hint
```scss
label.ng-invalid, input.ng-invalid.ng-dirty + small {
- [has() pseudo class](https://developer.mozilla.org/en-US/docs/Web/CSS/:has)
- [+ next-sibling combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Next-sibling_combinator)
:::

::: details Correction
```css
form.ng-dirty label:has(+ input.ng-invalid), form.ng-dirty input.ng-invalid + small {
color: red;
}
```
:::

4. Disable the Login and Register buttons using the `[disabled]` attribute if the form is invalid.
4. Disable the Login and Register buttons using the `[disabled]` attribute if the form is *invalid* and *dirty*.

5. Define a custom validator for the password field that refuses weak passwords. We will consider that a password is strong if it satisfies all of these requirements:
- Contains at least one uppercase character (regex `/^.*[A-Z]+.*$/`)
- Contains at least one lowercase character (regex `/^.*[a-z]+.*$/`)
- Has at least one non-alphanumeric character (regex `/^.*\W+.*$/`)
- Minimum length of 8 characters

Put that validator in `app/utils` and name it `password.validator.ts`. Here is its basic implementation:
You can use the `test` method on each pattern and pass it the value of the control to check if the pattern exists in it.

Put that validator in `app/utils` and name it `password.validator.ts`.

::: details Help
Here is its basic implementation:

```ts
export function password(): ValidatorFn {
Expand All @@ -193,8 +209,9 @@ export function password(): ValidatorFn {
}
}
```
:::

You can use the `test` method on each pattern and pass it the value of the control to check if the pattern exists in it. Add an error text via the `<small>` tag on the password field that shows if the form is dirty and the field has the `password.pattern` error.
Add an error text (`The password doesn't comply with the policy`) under the password field (use a `<small>` tag) that shows if the form is dirty and the field has the `password.pattern` error.

## Sources
- [Angular official forms documentation](https://angular.io/guide/forms-overview)
- [Angular official forms documentation](https://angular.dev/guide/forms-overview)
40 changes: 29 additions & 11 deletions docs/src/fr/forms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,37 +137,54 @@ Le composant suivant montre comment tirer parti :
Vous pouvez trouver une liste à jour des classes [ici](https://angular.io/guide/form-validation#control-status-css-classes).

## TP : Connexion et inscription avec des reactive forms
1. Implémentez le formulaire de connexion / inscription à l'aide de reactive forms et du form builder : remplacez le `[(ngModel)]` dans le template et supprimez les propriétés `email` et `mot de passe` de la classe du `LoginFormComponent`.
1. Implémentez le formulaire de connexion / inscription à l'aide de reactive forms et du form builder : remplacez le `[(ngModel)]` dans le template et supprimez les propriétés `email` et `mot de passe` de la classe du `LoginFormComponent` et déclarez un `FormGroup` et nommez le `loginForm`.

2. Ajoutez le validateur required (`Validators.required`) aux deux champs et affichez le texte `"Ce champ est requis"` sous chaque champ si le formulaire a un statut dirty et que ce champ a l'erreur `required` :

```html
<small>This field is required</small>
```

::: tip Hint
- Il est possible de récupérer une référence vers un *form control* en appelant la méthode `get('form control name')` du *form group*.
- Il est possible de vérifier la présence d'une erreur spécifique en appelant la méthode `hasError('error name')` d'un *form control*.
- Il est possible de récupérer la référence à une instance d'un `FormControl` en utilisant la propriété `controls` du `FormGroup` le contenant. Par exemple pour un `FormGroup` nommé *myFormGroup* et un `FormControl` nommé *myControl*:
```ts
myFormGroup.controls.myControl.touched
```
- Il est possible de vérifier si un `FormControl` (ou plus généralement un `AbstractControl`) a une erreur spécifique en appelant la méthode `hasError('error name')` de la classe `FormControl`.Par exemple pour un `FormGroup` nommé *myFormGroup*, un `FormControl` nommé *myControl* et une erreur *required* :
```ts
myFormGroup.controls.myControl.hasError('required')
```
:::

3. Stylisez le label et le texte d'erreur de chaque champ avec la classe `.ng-invalid` lorsque le formulaire est invalide et que ce champ n'est pas valide (rappelez-vous l'attribut `[class]`). Faites attention à ne bien styler que ces deux éléments pour chaque champ (vous pouvez utiliser le sélecteur CSS `+` à cet effet).
3. Stylisez le label et le texte d'erreur de chaque input s'étant fait attribuer la classe `.ng-invalid` par angular mais uniquement lorsque le formulaire a la classe `ng-dirty`. Faites attention à ne bien styliser que ces deux éléments pour chaque input (vous pouvez utiliser le combinateur CSS `+` et la pseudo-classe `has()` à cet effet).

::: details Hint
```scss
label.ng-invalid, input.ng-invalid.ng-dirty + small {
::: details Aide
- [has() pseudo classe](https://developer.mozilla.org/en-US/docs/Web/CSS/:has)
- [+ combinateur](https://developer.mozilla.org/en-US/docs/Web/CSS/Next-sibling_combinator)
:::

::: details Correction
```css
form.ng-dirty label:has(+ input.ng-invalid), form.ng-dirty input.ng-invalid + small {
color: red;
}
```
:::

4. Désactivez les boutons Connexion et Inscription à l'aide de l'attribut `[disabled]` si le formulaire n'est pas valide.
4. Désactivez les boutons Connexion et Inscription à l'aide de l'attribut `[disabled]` si le formulaire est *invalid* et *dirty*.

5. Définissez un validateur personnalisé pour le champ de mot de passe qui refuse les mots de passe faibles. Nous considérerons qu'un mot de passe est fort s'il satisfait à toutes ces exigences :
- Contient au moins un caractère majuscule (regex `/^.*[A-Z]+.*$/`)
- Contient au moins un caractère minuscule (regex `/^.*[a-z]+.*$/`)
- Possède au moins un caractère non alphanumérique (regex `/^.*\W+.*$/`)
- Longueur minimale de 8 caractères

Mettez ce validateur dans `app/utils` et nommez-le `password.validator.ts`. Voici son implémentation de base :
Vous pouvez utiliser la méthode `test` sur chaque pattern/regex et leur passer la valeur du form control pour vérifier si le pattern y est présent.

Mettez ce validateur dans `app/utils` et nommez-le `password.validator.ts`.

::: details Aide
Voici son implémentation de base :

```ts
export function password(): ValidatorFn {
Expand All @@ -193,8 +210,9 @@ export function password(): ValidatorFn {
}
}
```
:::

Vous pouvez utiliser la méthode `test` sur chaque pattern/regex et leur passer la valeur du form control pour vérifier si le pattern y est présent. Ajoutez un texte d'erreur via la balise `<small>` dans le champ du mot de passe qui indique si le formulaire est invalide et si le champ contient l'erreur `password.pattern`.
Ajoutez un texte d'erreur (`Mot de passe invalide`) via la balise `<small>` en dessous de l'input du mot de passe qui s'affiche si le formulaire est invalide et que l'input a l'erreur `password.pattern`.

## Sources
- [Documentation officielle des formulaires Angular](https://angular.io/guide/forms-overview)
- [Documentation officielle des formulaires Angular](https://angular.dev/guide/forms-overview)

0 comments on commit b754e93

Please sign in to comment.