Tribu Angular
Oxyl
NGULAR
Initial Request
Form Post
Client
Server
Page reload !
Initial Request
XHR
{ ... } JSON
Client
Server
Template
< >
Component
{ }
Injector
Service
{ }
LoginModule
{}
{{ person.name }}
(click)="handle()"
Metadata
Directive
{ }
Metadata
UserModule
{}
CardModule
{}
ListModule
{}
@NgModule({
declarations: any[],
imports: any[],
exports: any[],
providers: any[],
...
})
export class MonMondule {}Life Cycle Hooks
@Component({
selector: 'parent-component',
template: '<child-component></child-component>',
styleUrls: string[],
...
})
export class ParentComponent {}
@Component({
selector: 'child-component',
template: 'Salut les grands malades !'
})
export class ChildComponent {}@Injectable({
providedIn: 'root'
})
export class MonService {}
export class MonComponent {
constructor(private readonly service: Service) {}
}@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}<p appHighlight>Je suis surligné</p>
<p>Pas moi</p>{{ value }}
[property]="value"
(event)="handlerFunction($event)"
[(ngModel)]="property"
DOM
Component
<div>
Hello {{ name }}
</div><button (click)="doSomething()">
Click me !
</button>Liste des HTML DOM Events sans le "on" :
click, dblclick, mousedown, keypress, change, resize, blur, focus, ...
Root Component
Root Template
< >
Root Class
{ }
Child A Component
Child A Template
< >
Child A Class
{ }
Child B Component
Child B Template
< >
Child B Class
{ }
Grandchild Component
Grandchild Template
< >
Grandchild Class
{ }
ng new first-app
cd first-app
npm install
npm startng generate component components/recipeexport interface Ingredient {
name: string;
id?: number;
}ng generate module custom-materialpublic recipe: Recipe = {
description: "Les jolis voyages",
instructions: [
"Verser l’absinthe dans un verre. L’idéal serait un verre à absinthe, mais une petite coupe à dégustation peut faire l’affaire. Déposer la cuillère à absinthe sur le verre et y déposer le cube de sucre.",
"Faire couler l’eau de source glacée très doucement, quelques gouttes à la fois, sur le cube de sucre. Enfin, remuer l’absinthe avec la cuillère et servir.",
"À savourer en bonne compagnie, à 17 h, en écoutant de l’accordéon et en récitant Les Fleurs du Mal.",
""
],
name: "l'absinthe",
ingredients: [
{
ingredient: {
name: "absinthe"
},
quantity: 1,
unit: "Oz"
},
{
ingredient: {
name: "sucre"
},
quantity: 1,
unit: "cube"
},
{
"ingredient": {
"name": "eau de source glacée"
},
"quantity": 3,
"unit": "oz"
},
{
"ingredient": {
"name": "cuillère à absinthe perforée"
},
"quantity": 1,
"unit": "cuillère"
}
],
"picture": "https://boiremixologie.com/files/medias/_imageCarrousel/absinthe_cocktail_recette_classique_verte_fee_tradition.jpg"
}<ul>
<li *ngFor="let item of itemList">
{{ item }}
</li>
</ul><div *ngIf="expressionBooleenne">
Hello
</div>Paramètre d'entrée du composant :
@Input()
recipe: Recipe;<mon-composant-enfant [recipe]="maRecette"></mon-composant-enfant>Un peu d'aide côté design : Angular Material
Installation :
ng add @angular/materialPour les rapides: Mettre Angular Material dans un module; Créer un composant Header; Styliser tes composants
http://52.47.189.244:8080/swagger-ui.html#/
ng generate service recipenew Promise((resolve, reject) => { /* execution en asynchrone */ })
.then(result => { /* Traiter le résultat */ })
.catch(error => { /* Traiter l'erreur */ });La library JAVASCRIPT pour faciliter l'utilisation de l'asynchrone.
getRecipes(): Observable<Recipe[]> {
return of(RECIPES);
}Observable et Subject :
this.recipeService.getRecipes().subscribe({
next: (result: Recipe[]) => { /* Traiter le résultat */ },
error: (error) => { /* Traiter l'erreur */ }
});Pour en arriver où ?
Le Module : HttpClientModule
private recipeUrl = 'api/recipes';
constructor(private http: HttpClient) { }
getRecipes(): Observable<Recipe[]> {
return this.http.get<Recipe[]>(this.recipeUrl);
}Créer un module dédié : AppRoutingModule
L'importer dans le module principal
@NgModule({
exports: [
RouterModule
],
imports: [
RouterModule.forRoot(routes)
]
})
export class AppRoutingModule { }Définir une stratégie de route :
const routes: Routes = [
{
path: 'recipes',
component: RecipeListComponent,
pathMatch: 'full'
},
{
path: '**',
redirectTo: 'recipes',
pathMatch: 'full'
}
];<router-outlet></router-outlet>Point d'entrée des routes
Pour les rapides : Lors de la récupération des recettes, ajouter un tri par nom; Sur la page recipe ID, ajouter un "guard" dans le router pour vérifier que la recette existe
http://52.47.189.244:8080/swagger-ui.html#/
TIPS :
https://angular.io/guide/reactive-forms
Pour les rapides : Sur le formulaire d'ajout, forcer l'utilisation d'au moins une instruction et d'au moins un ingrédient, qu'une instruction ne peut pas être vide etc...
http://52.47.189.244:8080/swagger-ui.html#/
https://angular.io/guide/reactive-forms
@Pipe({
name: 'orderBy'
})
export class OrderByPipe implements PipeTransform {
transform(param : InputType): OutputType {
doSomething();
return newValue;
}
}https://angular.io/guide/animations#setup