Reputation: 221
I am trying to display a routerlink name based on a condition. I want to display the div section routerLink name if condition is true.If i check {{isNameAvailable}}
, first it displays false
and after this.names
got the values it shows true
.Since in the component getDetails()
method is asynchronous this.names
getting the values after html template render.Therefore this routerLink does n't display.Therefore I want to display div section after some time. (That 's the solution i have) Don't know whether is there any other solution.
This is my html file code.
<main class="l-page-layout ps-l-page-layput custom-scroll bg-white">
{{isNameAvailable}}
<div class="ps-page-title-head" >
<a *ngIf ="isNameAvailable === true" [routerLink]="['/overview']">{{Name}}
</a>
{{Name}}
</div>
</main>
This is my component.ts file
names= [];
isNameAvailable = false;
ngOnInit() {
this.getDetails()
}
getDetails() {
this.route.params.subscribe(params => {
this.names.push(params.Names);
console.log(this.names);
this.getValues().then(() => {
this.isNameAvailable = this.checkNamesAvailability(this.names);
console.log(this.isNameAvailable);
});
});
}
resolveAfterSeconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 900);
});
}
checkNamesAvailability(names) {
console.log(names);
return names.includes('Sandy');
}
async getValues() {
await this.resolveAfterSeconds(900);
}
And console.log(this.isLevelAvailable);
also true. What I can do for this?
Upvotes: 1
Views: 1766
Reputation: 161
1.You do not have anything to show in the HTML only the isNameAvailable
, because you do not have any assignment in the Name
variable.
2.It is better to use the angular build-in async pipe, when you want to show the returned value from observables.
3.When you are using the *ngIf
directive you can skip *ngIf ="isNameAvailable === true"
check because the variable is boolean type, you gust write *ngIf ="isNameAvailable"
, it will check also for null
but NOT for undefined
*ngIf
directive is responsible for checking and rendering the UI, you can see how many times the directive is checking by calling an function and print and answer in the console.Upvotes: 2
Reputation: 31115
You could use RxJS timer
function with switchMap
operator instead of a Promise to trigger something after a specific time.
Try the following
import { Subject, timer } from 'rxjs';
import { takeUntil, switchMap } from 'rxjs/operators';
names= [];
isNameAvailable = false;
closed$ = new Subject();
ngOnInit() {
this.getDetails()
}
getDetails() {
this.route.params.pipe(
switchMap((params: any) => {
this.names.push(params.Names);
return timer(900); // <-- emit once after 900ms and complete
}),
takeUntil(this.closed$) // <-- close subscription when `closed$` emits
).subscribe({
next: _ => {
this.isNameAvailable = this.checkNamesAvailability(this.names);
console.log(this.isNameAvailable);
}
});
}
checkNamesAvailability(names) {
console.log(names);
return names.includes('Sandy');
}
ngOnDestroy() {
this.closed$.next(); // <-- close open subscriptions when component is closed
}
Upvotes: 0
Reputation: 149
By any chance do you have changeDetection: ChangeDetectionStrategy.OnPush
docs set in component annotation? That might explain this behaviour. With it Angular run change detection only on component @Input()
's changes and since in your case there were non it did not run change detection which is why template was not updated. You could comment that line to check if that was cause of the issue. You are always able to run change detection manually via ChangeDetectorRef.detectChange()
docs which should solve you problem
constructor(private cd: ChangeDetectorRef) {}
...
getDetails() {
this.route.params.subscribe(params => {
...
this.getValues().then(() => {
this.isNameAvailable = this.checkNamesAvailability(this.names);
this.cd.detectChanges(); // solution
console.log(this.isNameAvailable);
});
});
}
This stackblitz show this bug and solution. You can read more about change detection here
Upvotes: 1