Moumoune
6/3/2017 - 2:55 PM

12. Les Formulaires pilotés par le template

*** Extraits de code : Les Formulaires pilotés par le template. ***

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { Pokemon } from './pokemon';
import { PokemonsService } from './pokemons.service';

@Component({
  selector: 'edit-pokemon',
  template: `
    <h2 class="header center">Editer {{ pokemon?.name }}</h2>
		<p class="center">
			<img *ngIf="pokemon" [src]="pokemon.picture"/>
		</p>
    <pokemon-form [pokemon]="pokemon"></pokemon-form>
  `,
})
export class EditPokemonComponent implements OnInit {

  pokemon: Pokemon = null;

  constructor(
    private route: ActivatedRoute,
    private pokemonsService: PokemonsService) {}

  ngOnInit(): void {
    let id = +this.route.snapshot.params['id'];
    this.pokemon = this.pokemonsService.getPokemon(id);
  }

}
.ng-valid[required], .ng-valid.required {
  border-left: 5px solid #42A948; /* bordure verte */
}

.ng-invalid:not(form) {
  border-left: 5px solid #a94442; /* bordure rouge */
}
<form *ngIf="pokemon" (ngSubmit)="onSubmit()" #pokemonForm="ngForm">
  <div class="row">
    <div class="col s8 offset-s2">
      <div class="card-panel">

        <!-- Pokemon name -->
        <div class="form-group">
          <label for="name">Nom</label>
          <input type="text" class="form-control" id="name"
                  required
                  pattern="^[a-zA-Z0-9àéèç]{1,25}$"
                 [(ngModel)]="pokemon.name" name="name"
                 #name="ngModel">

          <div [hidden]="name.valid || name.pristine"
                class="card-panel red accent-1">
                Le nom du pokémon est requis (1-25).
          </div>
        </div>

        <!-- Pokemon hp -->
        <div class="form-group">
          <label for="hp">Point de vie</label>
          <input type="number" class="form-control" id="hp"
                  required
                  pattern="^[0-9]{1,3}$"
                 [(ngModel)]="pokemon.hp" name="hp"
                 #hp="ngModel">
           <div [hidden]="hp.valid || hp.pristine"
                 class="card-panel red accent-1">
                 Les points de vie du pokémon sont compris entre 0 et 999.
           </div>
        </div>

        <!-- Pokemon cp -->
        <div class="form-group">
          <label for="cp">Dégâts</label>
          <input type="number" class="form-control" id="cp"
                  required
                  pattern="^[0-9]{1,2}$"
                 [(ngModel)]="pokemon.cp" name="cp"
                 #cp="ngModel">
           <div [hidden]="cp.valid || cp.pristine"
                 class="card-panel red accent-1">
                 Les dégâts du pokémon sont compris entre 0 et 99.
           </div>
        </div>

        <!-- Pokemon types -->
        <form class="form-group">
          <label for="types">Types</label>
          <p *ngFor="let type of types">
            <label>
              <input type="checkbox"
                class="filled-in"
                id="{{ type }}"
                [value]="type"
                [checked]="hasType(type)"
                [disabled]="!isTypesValid(type)"
                (change)="selectType($event, type)"/>
              <span [attr.for]="type">
                <div class="{{ type | pokemonTypeColor }}">
                  {{ type }}
                </div>
              </span>
            </label>
          </p>
        </form>

        <!-- Submit button -->
        <div class="divider"></div>
        <div class="section center">
          <button type="submit"
            class="waves-effect waves-light btn"
            [disabled]="!pokemonForm.form.valid">
            Valider</button>
        </div>

      </div>
    </div>
  </div>
</form>
<h3 *ngIf="!pokemon" class="center">Aucun pokémon à éditer...</h3>
import { Component, Input, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { PokemonsService } from './pokemons.service';
import { Pokemon } from './pokemon';

@Component({
	selector: 'pokemon-form',
	templateUrl: './app/pokemons/pokemon-form.component.html',
	styleUrls: ['./app/pokemons/pokemon-form.component.css']
})
export class PokemonFormComponent implements OnInit {

	@Input() pokemon: Pokemon; // propriété d'entrée du composant
	types: Array<string>; // types disponibles pour un pokémon : 'Eau', 'Feu', etc ...
	constructor(
		private pokemonsService: PokemonsService,
		private router: Router) { }

	ngOnInit() {
		// Initialisation de la propriété types
		this.types = this.pokemonsService.getPokemonTypes();
	}

	// Détermine si le type passé en paramètres appartient ou non au pokémon en cours d'édition.
	hasType(type: string): boolean {
		let index = this.pokemon.types.indexOf(type);
		if (index > -1) return true;
		return false;
	}

	// Méthode appelée lorsque l'utilisateur ajoute ou retire un type au pokémon en cours d'édition.
	selectType($event: any, type: string): void {
		let checked = $event.target.checked;
		if (checked) {
			this.pokemon.types.push(type);
		} else {
			let index = this.pokemon.types.indexOf(type);
			if (index > -1) {
				this.pokemon.types.splice(index, 1);
			}
		}
	}

	// Valide le nombre de types pour chaque pokémon
	isTypesValid(type: string): boolean {
		if (this.pokemon.types.length === 1 && this.hasType(type)) {
			return false;
		}
		if (this.pokemon.types.length >= 3 && !this.hasType(type)) {
			return false;
		}

		return true;
	}

	// La méthode appelée lorsque le formulaire est soumis.
	onSubmit(): void {
		console.log("Submit form !");
		let link = ['/pokemon', this.pokemon.id];
		this.router.navigate(link);
	}

}