I'd like to use linq in ngIf but I'm getting an error.
Typescript:
public selectedStrategies: IStrategy[] = [];
html:
<div *ngIf="selectedStrategies.find(s => s.id === 3)">
...
</div>
Error:
Parser Error: Bindings cannot contain assignments at column 28 in [selectedStrategies.find(s => s.id === 3)]
Is this not allowed or am I doing something wrong?
We/I might need more information about what you are trying to do, but you could skip the find
call and just set a property call current
or whatever you are wanting to call it, and then just update that property as needed.
To answer your main question, no, it isn't possible to call chainable array methods within an ngIf
or @if
.
There are a few ways to do this though.
One way would be to use angular's new signal
system with the computed
signal that would update everytime one of the signals changes:
@Component({
selector: 'app-example',
standalone: true,
imports: [CommonModule, FormsModule],
template: `
<div *ngIf="current() as itm">Item: {{ itm.name }}</div>
<p>
<input type="number" [(ngModel)]="id" />
</p>
`,
})
export class TestComponent {
id = signal(3);
items = signal([
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
]);
// Whenever any of the signals updates this will also update.
// Don't update signals here or you could end up in an endless loop.
current = computed(() => this.items().find(item => item.id === this.id()));
}
Another way would be to use a pipe and you could pipe the data through, this is good for not having to re-render hundreds of times as a function often will do.
@Pipe({ name: 'find', standalone: true })
export class FindPipe implements PipeTransform {
transform = (value: IStrategy[], id: number) => value.find(item => item.id === id);
}
@Component({
selector: 'app-example',
standalone: true,
imports: [CommonModule, FindPipe],
template: `
<div *ngIf="items | find: 3 as itm">
{{ itm.name }}
</div>
`,
})
export class TestComponent {
items = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
];
}
Another way is to have a single property and set the current state on that property:
@Component({
selector: 'app-example',
standalone: true,
template: `<div>{{ current.name }}</div> `,
})
export class TestComponent {
items = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
];
current = this.items[0];
setCurrent(id: number) {
this.current = this.find(item => item.id === id);
}
}