Component compilation lifecycle is handled by Angular compiler, so a component is unable to control its own lifecycle, and it should be controlled from the outside.
A common way to handle this is to use router. The lifecycle in route components differs from regular components because it's handled by router; they are attached to <router-outlet>
component. It's possible to prevent compilation in route components but not in regular components.
Otherwise this should be handled with a directive. ngIf
is built-in way to prevent the compilation of regular components.
So it becomes
<foo *ngIf="userService.isAllowed('see_trade_groups')"></foo>
Since this requires to inject userService
to parent component every time it's needed, this will result in a lot of boilerplate code. An appropriate solution is to create a directive that behaves similarly to ngIf
- or extend it to provide desired functionality:
import {Input, OnChanges, SimpleChanges, TemplateRef, ViewContainerRef} from '@angular/core';
import {NgIf, NgIfContext} from '@angular/common';
...
@Directive({
selector: '[role]'
})
class Role extends NgIf {
@Input() role: string;
constructor(
viewContainer: ViewContainerRef,
templateRef: TemplateRef<NgIfContext>
public userService: User
) {
super(viewContainer, templateRef);
}
ngOnChanges({ role }: SimpleChanges) {
this.ngIf = this.userService.isAllowed(role);
// can also subscribe to some observable to add/remove a component any time
}
}
Which is used like:
<foo *role="'see_trade_groups'"></foo>
Notice that Role
is *
structural directive. This allows it to control the compilation of an element it was specified on, similarly to how ngIf
and ngFor
do.