What am I doing wrong?
import {bootstrap, Component} from 'angular2/angular2'
@Component({
selector: 'conf-talks',
template: `<div *ngFor="let talk in talks">
{{talk.title}} by {{talk.speaker}}
<p>{{talk.description}}
</div>`
})
class ConfTalks {
talks = [ {title: 't1', speaker: 'Brian', description: 'talk 1'},
{title: 't2', speaker: 'Julie', description: 'talk 2'}];
}
@Component({
selector: 'my-app',
directives: [ConfTalks],
template: '<conf-talks></conf-talks>'
})
class App {}
bootstrap(App, [])
The error is
EXCEPTION: Template parse errors:
Can't bind to 'ngForIn' since it isn't a known native property
("<div [ERROR ->]*ngFor="let talk in talks">
Since this is at least the third time I've wasted more than 5 min on this problem I figured I'd post the Q & A. I hope it helps someone else down the road... probably me!
I typed in
instead of of
in the ngFor expression.
Befor 2-beta.17, it should be:
<div *ngFor="#talk of talks">
As of beta.17, use the let
syntax instead of #
. See the UPDATE further down for more info.
Note that the ngFor syntax "desugars" into the following:
<template ngFor #talk [ngForOf]="talks">
<div>...</div>
</template>
If we use in
instead, it turns into
<template ngFor #talk [ngForIn]="talks">
<div>...</div>
</template>
Since ngForIn
isn't an attribute directive with an input property of the same name (like ngIf
), Angular then tries to see if it is a (known native) property of the template
element, and it isn't, hence the error.
UPDATE - as of 2-beta.17, use the let
syntax instead of #
. This updates to the following:
<div *ngFor="let talk of talks">
Note that the ngFor syntax "desugars" into the following:
<template ngFor let-talk [ngForOf]="talks">
<div>...</div>
</template>
If we use in
instead, it turns into
<template ngFor let-talk [ngForIn]="talks">
<div>...</div>
</template>
TL;DR;
Use let...of instead of let...in !!
If you're new to Angular (>2.x) and possibly migrating from Angular1.x, most likely you're confusing in
with of
. As andreas has mentioned in the comments below for ... of
iterates over values
of an object while for ... in
iterates over properties
in an object. This is a new feature introduced in ES2015.
Simply replace:
<!-- Iterate over properties (incorrect in our case here) -->
<div *ngFor="let talk in talks">
with
<!-- Iterate over values (correct way to use here) -->
<div *ngFor="let talk of talks">
So, you must replace in
with of
inside ngFor
directive to get the values.
for..in
iterates the object's keys/properties while for...of
iterates the object's values. for(prop in foo) {}
is the same as for(prop of Object.keys(foo)) {}
. This is a new language feature of ECMA Script 2015 / ES6. So this is only remotely an Angular issue.
There is an alternative if you want to use of
and not switch to in
. You can use KeyValuePipe
introduced in 6.1. You can easily iterate over an object:
<div *ngFor="let item of object | keyvalue">
{{item.key}}:{{item.value}}
</div>
Try to import import { CommonModule } from '@angular/common';
in angular final as *ngFor
,*ngIf
all are present in CommonModule
use of instead of in. You can use KeyValue Pipe . You can easily iterate over an object:
<div *ngFor="let items of allObject | keyvalue">
{{items.key}}:{{items.value}}
</div>
In my case, WebStrom auto-complete inserted lowercased *ngfor
, even when it looks like you choose the right camel cased one (*ngFor
).
My problem was, that Visual Studio somehow automatically lowercased *ngFor
to *ngfor
on copy&paste.
Basically, if you create a popup using a new class, so at that time you have to add that class under the
declarations: []
In base.module.ts or app.module.ts
My Example code
##########################MY COMPONENT##################################
@Component({
selector: 'app-modal-content',
templateUrl: './order-details.html',
encapsulation: ViewEncapsulation.None,
styles: []
})
export class NgbdModalContent {
@Input() orderDetails: any;
private orderId;
private customer;
private orderDate;
private shipDate;
private totalAmount;
private salesTax;
private shippingCost;
private transactionStatus;
private isPaid;
private isMailSent;
private paymentDate;
// private orderDetails;
constructor(public activeModal: NgbActiveModal) {
}
}
###########################BASE MODULE#################################
@NgModule({
imports: [
CommonModule,
FormsModule
],
declarations: [
NavbarsComponent,
NgbdModalContent,
]
})
export class BaseModule { }
Q:Can't bind to 'pSelectableRow' since it isn't a known property of 'tr'.
A:you need to configure the primeng tabulemodule in ngmodule
my solution was - just remove '*' character from the expression ^__^
<div ngFor="let talk in talks">
Success story sharing
#
before thetalk
variable (as your said: "hope it helps someone else down the road... probably me!")