JordanFrankfurt JordanFrankfurt - 4 years ago 148
TypeScript Question

Using observables in an Angular 2 template with *ngFor

I am unable to access a property of an object provided by the async pipe if I build the access chain using *ngFor.

In the example below, suppose that

Parking
in the test line and the
?.[filter.propName]
two lines beneath represent the same key on the same object. The test line will evaluate to true, but the checked property does not. Why? How do I access the propery when stamping these out with *ngFor?

For example, if
{{(compModel | async)?.Parking?.Garage}} === true
I would expect
{{(compModel | async)?.[filter.propName].instance}} === true
as well, but this isn't the case.

The syntax below doesn't work. I'm using it to demonstrate intended functionality.

<div *ngFor="let filter of filters | async">
...
<fieldset class="filter-category-title">
<legend>{{filter.name}}</legend>
<label *ngFor="let instance of filter.options">
test: {{(compModel | async)?.Parking.instance}}
<input type="checkbox"
checked={{(compModel | async)?.[filter.propName].instance}}
(click)="amenityEmit({category: filter.propName, filter: instance, resetCategory: false})">
{{instance}}
</label>
</fieldset>
</div>


The filter data I get from the server in the format below. I use this to build a comparison model, also below, which is how I manage the state of my search results page. (
[key: string]
is always a propName from a Filter).

export interface Filter {
base: boolean,
filter: string,
propName: string,
unionType: string,
inputType: string,
options: {
options: string[],
sectionTitle: string
}[] | string[]
}


compModel interface:

export interface CompModel {
[key: string]: {
touched: boolean
unionType: string,
options: {
options: string[],
sectionTitle: string
}[] | string[],
updateSelf(x: CompModel, y: Action): void
}
}

Answer Source

The safe-navigation operator ?. does not work with []. There is no ?[] operator and also no ?.[] or .[] operator, therefore this can't work.

You can try

{{(compModel | async) && (compModel | async)[filter.propName].instance}} === true

otherwise you'll need to move some code to the components class

for example

this.compModel = someService.getSomeObservable()
.filter(val => !!val)

to ensure there are no null values

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download