This question already has answers here:
Can't bind to 'ngForOf' since it isn't a known property of 'tr' (final release)
(38 answers)
Closed 3 years ago.
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?
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.
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 { }
In Angular2 beta ng-for isn't correct. it should be *ngFor.
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
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.
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.
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
Be careful of the typo:
it's
*ngFor
not ng-for
not ngfor
not ng-For
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
...
...
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').
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.
Related
I have one feature module that I created via CLI, so it imports the common module.
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { HomeComponent } from './home/home.component';
#NgModule({
declarations: [HomeComponent],
imports: [
CommonModule
]
})
export class HomeModule { }
But when I do this normal paragraph appears but paragraph with *ngFor part doesn't work, it does not display anything.
<p> Some normal paragraph </p>
<p *ngFor = "let i of [1,2,3]" >home works!</p>
I also tried to create a shared module, import and export the common module there, and import that shared module in my feature module but it didn't work.
What could cause the problem?
I have also faced that problem. after looking at my app.module.ts I found that shared my custom module is not imported there. After importing it in app module my problem has been solved
I am using Angular 5 with Angular material and WebStorm version 2017.3.1
When I try to use the <mat-toolbar> element with the following code
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import {MatToolbarModule} from '#angular/material';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
MatToolbarModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.html
<mat-toolbar>
<span>Title</span>
</mat-toolbar>
WebStorm gives me an error:
'mat-toolbar' is not a known element:
1. If 'mat-toolbar' is an Angular component, then verify that it is part of this module.
However, this renders correctly in the browser:
Because it is included in the module with this line import {MatToolbarModule} from '#angular/material'; and
imports: [
BrowserModule,
MatToolbarModule
],
Is there something I'm missing here? Why does WebStorm (and also when running tests via ng test) give me this error? How can I prevent this error/warning?
This error is generated via TypeScript.
You can see the error in the console if you click on the TypeScript tab at the bottom.
It's possible to make this error go away if you force the TypeScript service to restart by clicking on the arrow in a circle.
This requires a compile first.
So far, I cannot find a way to map this to a shortcut.
Thanks to #lena and #Z.Bagley for helping me figure this out.
The error comes from Angular language service.
Looks related to https://github.com/angular/angular/issues/14961; see if updating Typescript to 2.5.2+ helps
I know this isn't the problem the OP had, but wanted to share this in case someone comes across this post and is still experiencing this problem in WebStorm and are not getting TypeScript compile errors, here's what worked for me: In WebStorm select menu item File > Invalidate Caches / Restart. This problem happened to me in WebStorm 2019.3 .
https://angular.io/guide/architecture#services
I'm following the docs on angular.io to inject dependencies like services, etc. I did everything they said and when I try to run it, the console keeps telling me:
Uncaught ReferenceError: LedgerService is not defined
I am doing nothing crazy except creating a simple component with a service where both constructors have console.log commands (constructors in both the component and service). I've done everything Angular says to do in their 2 paragraphs that details this feature of Angular.
The component itself is being injected into the main app module (with the service being injected into the component) and both the component and service were created with the Angular CLI. So there isn't much I've even done at all minus trying to inject the service. So I'm not sure where it is going wrong but it is definitely not working and just shows a blank page (when it previously had basic content by default).
I created both units, tried to specify providers in both the app.module and the component.ts file and neither works and yields the same error--when Angular claims either could work. I've also specified it as a private service within the constructor of the component.ts file.
Everything I've seen relating to this is always for Angular 1 or 2. Neither of which are even remotely similar to Angular 4/5.
If you really want to see this code, fine but it's literally just framework and nothing else:
bookkeeper.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-bookkeeper',
templateUrl: './bookkeeper.component.html',
styleUrls: ['./bookkeeper.component.css'],
providers: [LedgerServiceService]
})
export class BookkeeperComponent implements OnInit {
constructor(private service: LedgerServiceService) { }
ngOnInit() {
console.log("Ledger component works!");
}
}
app.module.ts:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { InterfaceComponent } from './interface/interface.component';
import { BookkeeperComponent } from './bookkeeper/bookkeeper.component';
#NgModule({
declarations: [
AppComponent,
InterfaceComponent,
BookkeeperComponent
],
imports: [
BrowserModule
],
providers: [
LedgerServiceService
],
bootstrap: [AppComponent]
})
export class AppModule { }
ledger-service.service.ts:
import { Injectable } from '#angular/core';
#Injectable()
export class LedgerServiceService {
constructor() {
console.log("wtf");
}
}
LedgerService is actually called LedgerServiceService because I initially created LedgerService manually and then tried to use the AngularCLI to generate a service and named it LedgerService and it created a service called LedgerServiceService. Naming is not what is wrong. I only initially called it simply LedgerService because I figured it would be confusing.
Your examples are missing the import.
Anywhere we use a custom type, we also need to import that type.
For that reason, in both the module and component you will need to add:
import { LedgerServiceService } from './your-path-here'
You can see this in the examples they give on https://angular.io/guide/dependency-injection
In the below code from ../src/app/app.module.ts,
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
Component consists:
view(../src/app/app.component.html)
logic(../src/app/app.component.ts)
style(../src/app/app.component.css)
Angular application is a tree of components. Good components have high cohesion, i.e. each component contains only elements with related functionality. They are also well encapsulated and loosely coupled.
How modules are different from components?
A component is just a class with the #Component() annotation. Note that .html and .css files might be referenced by the component, certainly not mandatory. The component template might very well be 'inlined' directly in the component configuration, or there simply might not be any html template at all for a given component.
A module is a structural element of an Angular application (and maybe other classes and interfaces). It is also "just a class" with the #NgModule() annotation.
It acts as a logical 'container' for your components, directives, services, pipes, etc... to help you structure your overall source code better.
You can have a look at this existing question : What's the difference between an Angular component and module
A module is something that has components. It wraps them up so you can import and manage them.
Notice when you make a component you can put anything that's decorated as #Injectable in your constructor:
#Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
constructor(private myService: MyService) { }
ngOnInit() {
}
}
And magically you will have a myService to use. This is dependency injection, which is built into Angular - but it's managed on a Module level. In your module you import what other modules you want to be able to use:
imports: [
BrowserModule,
FormsModule
],
define what your module includes:
declarations: [
AppComponent,
HeroesComponent,
MyService
],
export any components (so other modules can import them)
exports: [
HeroesComponent
],
They help organize an application into blocks of functionality. Components are things that tell angular how to render something. Modules compose Components, Pipes, Services etc into 'blocks' that can be compiled by angular or imported and used by others.
Edit to address comment
Taking your specific question about HttpClient. The HttpClient is the service you are using to perform the actions. The HttpClientModule is the module you import into your module, so you can use the service it contains.
You import the module:
#NgModule({
imports: [
BrowserModule,
// Include it under 'imports' in your application module
// after BrowserModule.
HttpClientModule,
],
})
And use the service:
#Component(...)
export class MyComponent implements OnInit {
// Inject HttpClient into your component or service.
constructor(private http: HttpClient) {}
...
}
The HttpClientModule contains within it all you need for the HttpClient to work, and packages it up so you can use it in your own projects.
This particular module only wraps up that one service, but the module could contain a bunch of related services, components, pipes or directives. For example, the RouterModule allows you to use the RouterOutlet and RouterLink directives.
Module in angular is set of Components, Services, Filters, or some another smaller modules too, or we can say where you import all these in order to use later in the app for future use. in a single app there can be one or more than one module may exist.
Whereas, A component controls a patch of screen called a view.
You define a component's application logic—what it does to support the view—inside a class. The class interacts with the view through an API of properties and methods.
Refer this guide for more details:
https://angular.io/guide/architecture
I am pretty new in Angular 2. I am studying how to create modules into an Angular app and I have the following doubt related a tutorial that I am following.
My doubt is related to the routing.
So in my example there is defined this AuthModule module:
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { SigninComponent } from './signin/signin.component';
import { SignupComponent } from './signup/signup.component';
import { AuthRoutingModule } from './auth-routing.module';
#NgModule({
// Components and directives used by the module:
declarations: [
SigninComponent,
SignupComponent
],
// Import modules used by this features module:
imports: [
FormsModule,
AuthRoutingModule
]
})
export class AuthModule {}
and I have the related rotues configuration class defined:
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { ShoppingListComponent } from './shopping-list/shopping-list.component';
const appRoutes: Routes = [
{ path: '', redirectTo: '/recipes', pathMatch: 'full' },
{ path: 'shopping-list', component: ShoppingListComponent }
];
#NgModule({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
So I think that the export keyword means that the content related to this class can be exported and used somewhere else (in this case I think into the imports array of the AuthModule class).
Is it? Or am I missing something? What it the exact meaning of the export statment?
I am not understanding if it is something related to Angular or more generally to TypeScript (because here I found https://www.typescriptlang.org/docs/handbook/modules.html). So it seems to me that this module concept is not directly bounded to Angular 2 framework but is a TypeScript concept to subdivide our code in a smart way (then Angular 2 can use this kind of feature of the language).
Is it or am I missing something?
Angular imports/exports and TypeScript imports/exports are two different concepts.
TypeScript imports/exports work at language level to make it clear what
a used identifier references exactly. This is entirely unrelated to Angular.
So, if you use FormsModule there can't be any ambiguity, what FormsModule is meant. If there is more than one FormsModule in your code or any of your dependencies, then you need to make it clear with imports which one is meant. You can't import 2 FormsModule from different locations without disambiguation (for example using as foo in the import and then reference it using foo.FormsModule).
This way you can use code from arbitrary 3rd-party libraries and avoid name collisions.
Angular imports/exports are used to make the content of one module available to be used in another module.
Your:
imports: [
FormsModule,
AuthRoutingModule
]
Allows you to use the directives from FormsModule and AuthRoutingModule in AuthModule and registers the services provided by these modules in the AppModule scope or the closed lazy-loaded root scope.
If you reference any of Angulars directives or services in TypeScript code, you also need to add TypeScript imports. Above FormsModule and AuthRoutingModule need to be imported with TypeScript imports, to make the Angular imports: [...] work.
For example like
<form #f="ngForm">
<input type="text">
</form>
works only if FormsModule is listed in imports: [ ... ] of your current module.
There is no TypeScript import required, because there is no TypeScript code.
Yes you are right by using export keyword before your typescript class you can use that class somewhere else .. in your project