104

I am trying to follow the basic Angular 2 tutorial here:

https://angular.io/docs/js/latest/guide/displaying-data.html

I can get the angular app to load and display my name with this code:

import { Component, View, bootstrap } from 'angular2/angular2';

@Component({
    selector: "my-app"
})

class AppComponent {
    myName: string;
    names: Array<string>;
    constructor() {
        this.myName = "Neil";

    }

}
bootstrap(AppComponent);

However when I try to add an array of strings and try to display them with an ng-for, it is throwing the following error:

Can't bind to 'ng-forOf' since it isn't a known native property ("
    <p>Friends:</p>
    <ul>
        <li [ERROR ->]*ng-for="#name of names">
        {{ name }}
        </li>
"): AppComponent@4:16
Property binding ng-forOf not used by any directive on an embedded template ("
    <p>Friends:</p>
    <ul>
        [ERROR ->]<li *ng-for="#name of names">
        {{ name }}
        </li>
"): AppComponent@4:12

Here is the code:

import { Component, View, bootstrap } from 'angular2/angular2';

@Component({
    selector: "my-app"
})

@View({
    template: `
        <p>My name: {{ myName }}</p>
        <p>Friends:</p>
        <ul>
            <li *ng-for="#name of names">
                {{ name }}
            </li>
        </ul>
    `,
    directives: [ NgFor ]
})

class AppComponent {
    myName: string;
    names: Array<string>;
    constructor() {
        this.myName = "Neil";
        this.names = ["Tom", "Dick", "Harry"];
    }

}
bootstrap(AppComponent);

What am I missing?

peterh
  • 11,875
  • 18
  • 85
  • 108
Neil
  • 2,659
  • 7
  • 35
  • 57
  • Sometimes it happens because of failed plugin in IDE (VS Code, Web Storm). Check my answer here: https://stackoverflow.com/a/70368326/4079915 – Experimenter Dec 15 '21 at 18:12
  • I got this error because I forgot to import the module (where ngfor was being used) into app.module. – John Gilmer Jul 25 '23 at 02:04

11 Answers11

156

If you use alpha 52, check out the CHANGELOG.md in the GitHub repo. They changed the template to case-sensitive which is ngFor instead of ng-for (similar for all other directives)

Element names like <router-outlet> weren't changed though to stay compatible with custom elements spec which requires a dash in the tag name of custom elements.

In >= RC.5 (and final) ngFor and similar directives are not ambient by default. They need to be provided explicitly like

@NgModule({
  imports: [CommonModule],

or if you don't mind the module being locked to be browser-only

@NgModule({
  imports: [BrowserModule],

The BrowserModule exports CommonModule like also WorkerAppModule does.

Update

The BrowserModule should be imported in the app module, in other modules CommonModule should be imported instead.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
34

With Angular 2.1.0+

It seems this is the same except you should import the BrowserModule in your app module and import CommonModule in others (you can't import BrowserModule twice with routes lazy-loading).

With Angular 2 rc5 :

This version introduced NgModules, you need to import BrowserModule in your module(s) in order to use ngFor, and ngIf:

BrowserModule registers critical application service providers. It also includes common directives like NgIf and NgFor which become immediately visible and usable in any of this modules component templates.

example:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';


@NgModule({
  imports: [BrowserModule],
  providers: [],
  exports: [],
  declarations: []
})
export class MyModule { }
n00dl3
  • 21,213
  • 7
  • 66
  • 76
  • Thanks for this, I was pulling my hair out looking at all the posts saying I am misspelling things but I was missing this import. – taylorjonl Sep 09 '16 at 20:29
  • i wanted to add my thanks... I moved my code to a feature module and was tearing my hear out trying to figure out what I had messed up. – birwin Dec 06 '16 at 16:00
15

In Angular2 beta ng-for isn't correct. it should be *ngFor.

SnareChops
  • 13,175
  • 9
  • 69
  • 91
11

ngIf and ngFor are declared in CommonModule from @angular/common.

CommonModule contributes many of the common directives that applications need including ngIf and ngFor.

BrowserModule imports CommonModule and re-exports it. The net effect is that an importer of BrowserModule gets CommonModule directives automatically.

update your code as follow

import { CommonModule } from '@angular/common';

@NgModule({
imports: [CommonModule]
})
// In HTML
<li *ngFor="let customer of customers">{{customer.name}}</tr>

for more information Angular Module

Praveen M P
  • 11,314
  • 7
  • 34
  • 41
6

The syntax for the ngFor directive is

<tr *ngFor="let name of names">{{name}}</tr>

Notice that is no longer #name of names as it was but let name of names and the ngFor requires the * and is case sensitive.

Gary
  • 602
  • 9
  • 7
4

Behind the other answers, another possible cause is that you use some html formatter-repacker which converts all of your HTML - including the component templates - into lowercase.

The Angular template substitution is case sensitive for the ngFor and ngIf tags, at least today, but I can't say anything for sure for the next week.

Particularly webpack plugins, for example htmljs or html-minify work badly as their convert everything to lowercase on their default setting. Doublecheck the HTML code in the compiled text, it may be with all lowercase (like *ngif=...), which won't be accepted, even if in your original source is it correct!

Of course it breaks the HTML5 standard.

It happens because our most wonderful angular2 development thinks "they wish to follow html5 more closely", but there are always some surprising exceptions, making the work with angular2 always better and better.

Community
  • 1
  • 1
peterh
  • 11,875
  • 18
  • 85
  • 108
  • There's more than one issue with minimizing your HTML before passing it to the Angular template compiler, for example, by default it removes quotes around attributes, which the template compiler (sometimes) can't handle. It's going to get minimized anyway (you're definitely using AOT by now, right?) so just disable minimization : `test: /\.component\.html$/, use: { loader: "html-loader", options: { minimize: false } }` – Coderer Apr 13 '18 at 12:22
3

It also might be caused by a typo. I just faced this problem I had

<div class="row" *ngFor="let order or orders">

As you see there is let order or orders instead of let order of orders

Timothy
  • 3,213
  • 2
  • 21
  • 34
2

Be careful of the typo: it's

*ngFor

  • not ng-for
  • not ngfor
  • not ng-For
Yassin
  • 1,376
  • 18
  • 18
2

Angular 8 Solution

Source Link

How to resolve this issue?

To resolve this issue we need to import BrowserModule in the application's main module i.e app.module.ts file and also import CommonModule in the child module.

So after imports, our files will look like these:

app.module.ts

    // app.module.ts
    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';

    ...
    ...

    @NgModule({
        imports: [
            BrowserModule,
            ....
            ....

child.module.ts

    // child.module.ts
    ...
    ...
    import { CommonModule } from '@angular/common';

    @NgModule({
      imports: [
        CommonModule
        ...
        ...
JeffryHouser
  • 39,401
  • 4
  • 38
  • 59
Code Spy
  • 9,626
  • 4
  • 66
  • 46
1

Given that it has had so much success on the other issue marked as a duplicate of this one, here is a response of mine that has received a lot of upvotes:

Just for anyone who is missing it, I also had an issue where I typed ngif rather than ngIf (notice the capitol 'I').

dudewad
  • 13,215
  • 6
  • 37
  • 46
1

My problem was caused by a missing export of the component containing the *ngFor. This component (MyComponentWithNgFor) was already imported and declared inside my SharedModule. The SharedModule also imported Angular's CommonModule, so everything looked fine.

However, I was using my component with the *ngFor in another module - let's call it ModuleB - which was importing SharedModule, so that I could use MyComponentWithNgFor.

My solution was simply to add my component containing the *ngFor to my SharedModule's exports array, like so:

@NgModule({
  imports: [ CommonModule ],
  declarations: [ MyComponentWithNgFor ],
  exports: [ MyComponentWithNgFor ]
})
export class SharedModule { }

This made it possible for my ModuleB (which imports SharedModule) to use MyComponentWithNgFor.

Ittit
  • 321
  • 2
  • 6