enable.service.ts
@Injectable({
providedIn: 'root'
})
export class EnableService {
isEnabled$ = from(this.client.init()).pipe(
switchMap(() => this.client.getEnabled()),
map(([enabled, isAdmin]) => ({enabled: true, isAdmin: false})),
share()
); // not exactly like this but some kind of observable that will return enable and isAdmin
constructor(
// some constructor
) {}
}
main.component.ts
export class MainComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('mymap') containerRef: ElementRef<HTMLDivElement>;
isAdmin: boolean = false;
isEnable: boolean = false;
constructor(
private enableService: EnableService,
) {
this.enableService.isEnabled$.subscribe(res => {this.enable = res.enabled; this.isAdmin = res.isAdmin});
}
async ngAfterViewInit(): Promise<void> {
// HACK: need to wait the enableService subscription to get the actual value, otherwise containerRef #mymap is not known whether it is exist or not
await new Promise(resolve => setTimeout(resolve, 1000));
// have to exist so we can hide/remove the map properly
if (this.containerRef) {
// some third party sdk initialization should only get executed if containerRef exist
}
}
main.component.html
<div #mymap *ngIf="!isEnable || isAdmin"></div>
right now this is a working code, with some hack of 1 second delay inside ngAfterViewInit. The problem is what happened if the enableService take half a second longer, it will break.
Is there anyway to make sure ngAfterViewInit got executed after enableService retrieve the value?
or is there a better way so I don’t have to use that 1 second delay. If I set the initial value of isEnable to false, and then it ended up true, it will cause an issue, likewise if it’s true and ended up true, it will cause error too. I tried moving the observable subscription from constructor to ngOnInit, it also does not work.
2
Answers
Does this work?
Create a child component inside the NgIf, so that it will trigger the ngafterviewinit after the *ngIf becomes true!
ts
html
You can add a setter for your containerRef:
In the setter function you will get all the changes if an element appears, if disappears and you do not have to sync manually with a service call.