Reputation: 236
I have a table of data and one column has a button in it that opens a dialog popup based on the object from that row. I am trying to show/hide the button based on a http request that has to be called once per button to determine if the button should show/hide for that row. I set up a network call like this:
setupApi() {
return this.http.get(url);
}
shouldShowButton() {
this.service.getJson()
.subscribe(data => {
return true;
}, error => {
return false;
});
}
And then on my button I have this:
<button mat-raised-button *ngIf="shouldShowButton() | async"></button>
I am getting error on the ng-if saying my function returns void.
Upvotes: 1
Views: 1305
Reputation: 73357
I would restructure this a bit, and handle all request in the TS before displaying.
Reading your comments, we can gather....
If you have an unknown amount of items, you can use forkJoin
to perform all requests in parallel based on the original array, then add the value to your original array that you are looping in your table in template. I would add a boolean prop in your array, where we determine that should the button be shown or not, here called showBtn
So Let's say your data looks like (after adding the bool prop):
myDat = [
{ name: "name1", showBtn: false },
{ name: "name2", showBtn: false },
{ name: "name3", showBtn: false },
{ name: "name4", showBtn: false }
];
Use array map
to push requests to a helper array, which we then use forkJoin
on, then add the boolean value to your original array:
shouldShowButton() {
let reqs = [];
this.myDat.map(btn => reqs.push(this.myService.getJson(btn.name)));
this.myData = forkJoin(...reqs).pipe(
map(val => {
return val.map((curr, i, arr)=> {
return {... this.myDat[i], showBtn: curr}
})
})
)
}
now you have all data you need inside the observable myData
, which you can use in the template like:
<tr *ngFor="let item of myData | async">
<td>
{{item.name}}
</td>
<td>
<button *ngIf="item.showBtn" (click)="doSomething(item)">Button!</button>
</td>
</tr>
Upvotes: 1
Reputation: 190
async pipe doesn't work like that, also your approach to show hide a button is not correct as there might several thousands of rows in the table and calling an api this many time is not good for the application performance.
You can try below:
Upvotes: 0
Reputation: 979
The async pipe expects an Observable. I would recommend using a variable instead of a function (to keep it simple and because running functions in your template is 'bad practice') like:
public showButton: boolean;
ngOnIinit() {
this.shouldShowButton();
}
shouldShowButton() {
this.service.getJson().subscribe(data => {
this.showButton = true;
}, error => {
this.showButton = false;
});
}
<button mat-raised-button *ngIf="this.showButton"></button>
For an 'unknown amount of buttons' you could use an object.
public showButtons: any = {};
ngOnIinit() {
this.shouldShowButton('button1');
this.shouldShowButton('button2');
this.shouldShowButton('button2');
....
}
shouldShowButton(buttonName: string) {
this.service.getJson(buttonName).subscribe(data => {
this.showButtons[buttonName] = true;
}, error => {
this.showButtons[buttonName] = false;
});
}
<button mat-raised-button *ngIf="this.showButtons['button1']"></button>
<button mat-raised-button *ngIf="this.showButtons['button2']"></button>
<button mat-raised-button *ngIf="this.showButtons['button3']"></button>
Upvotes: 2
Reputation: 6811
An *ngIf
with the async
pipe is expecting an Observable. You give a Subscription instead.
.ts
Upvotes: 0