Componente dinamice - sunt create la runtime, momentul cand vor trebui sa fie afisate este controlat programatic, cu *ngIf sau cu Dynamic Component Loader
Dynamic Component Loader: componenta este adaugata la DOM prin cod (imperativ) (vs. declarativ, printr-un selector, la *ngIf)
Totusi, varianta prin *ngIf este mai usoara si cea recomandata.
Exemplu cu *ngIf pentru afisarea unei ferestre de eroare:
1. se creeaza o componenta noua, numita de exemplu AlertComponent, cu satelitii aferenti, si se importa in app.module.ts langa celelalte componente.
@Component({ selector: 'app-alert', templateUrl: './alert.component.html', styleUrls: ['./alert.component.css'] })
2. In componenta se adauga:
@Input() message: string; // string settable from outside@Output() closeEvent = new EventEmitter<void>(); // emits on onClose() for the outside
3. In Html, fereastra de alerta are un buton cu textul "Close", se adauga: (click)="onClose()" pentru a declansa emitter-ul din Typescript.
4. Componenta de alert este folosita in componenta din care vrem s-o chemam, cu *ngIf, trimitandu-i drept input [message] o variabila, iar pe output-ul (closeEvent) devenit input in acea componenta, se merge pe o metoda onHandleError din componenta curenta:
<app-alert [message]="error" *ngIf="error" (closeEvent)="onHandleError()"></app-alert>
5. In onHandleError() avem grija sa schimbam conditiile pentru care *ngIf este true, deci putem seta this.error = null acolo.
----
Varianta programatica ( mai grea, pentru acelasi scenariu )
1. Se creeaza o componenta noua, adnotata cu @Directive, care va reprezenta definitia unui obiect in DOM (de fapt gata sa fie introdus in DOM). ViewContainerRef reprezinta "un container unde se pot adauga una sau mai multe view-uri la componenta"
@Directive({ selector: '[appPlaceholder]'}) export class PlaceholderDirective { constructor(public viewContainerRef: ViewContainerRef) { } }
2. In Html-ul componentei unde vrem sa atasam componenta dinamica, declaram (este doar o declaratie, nu apare in DOM):
<ng-template appPlaceholder></ng-template>
3. In TypeScript-ul componentei de mai sus vom realiza adaugarea programatica. Dar intai declaram variabilele clasei:
@ViewChild(PlaceholderDirective) alertHost: PlaceholderDirective; private closeSub: Subscription;
4. Se injecteaza in constructor: private componentFactoryResolver: ComponentFactoryResolver
Intr-o metoda de showErrorAlert():
5. Se obtine din alertHost proprietatea de tipul ViewContainerRef declarata, se face clear() pe ea
6. Din "fabrica" de componente se obtine sub-fabrica de tipul AlertComponent:
const alertCompFactory = this.componentFactoryResolver.resolveComponentFactory(AlertComponent);
7. Se creeaza componenta dinamica cu ajutorul ei si se populeaza campul message cu ceva ce ar trebui sa primim ca parametru in metoda:
const componentRef = hostViewContainerRef.createComponent(alertCompFactory); componentRef.instance.message = errorResponse;
8. Se face subscribe pe pe proprietatea closeEvent a componentei, care se salveaza intr-o subscriptie:
this.closeSub = componentRef.instance.closeEvent.subscribe(() => { this.closeSub.unsubscribe(); hostViewContainerRef.clear(); });
Asadar, cand se apasa pe "Close", subscriptia in curs se termina, iar componenta se "curata" astfel disparand de pe ecran.
9. Metoda de mai sus este chemata pe ramura de tratare a erorii dupa login/logout.
Niciun comentariu:
Trimiteți un comentariu