1
votes

I am trying to Implement A Reactive form in one of the Lazy Loaded Component and I am getting the following error.

Stackblitz Link

ERROR Error: Uncaught (in promise): Error: Template parse errors:
Can't bind to 'formGroup' since it isn't a known property of 'form'. ("<h3>Product List</h3>

<form [ERROR ->][formGroup]="myForm">

    <input type="text" formControlName="name"/>
"): ng:///ProductsRoutingModule/ProductListComponent.html@2:6
Error: Template parse errors:
Can't bind to 'formGroup' since it isn't a known property of 'form'. ("<h3>Product List</h3>

<form [ERROR ->][formGroup]="myForm">

    <input type="text" formControlName="name"/>
")

package.json

{
  "name": "angular6-lazy-loading",
  "version": "0.0.0",
  "private": true,
  "dependencies": {
    "rxjs": "6.1.0",
    "core-js": "2.5.5",
    "zone.js": "0.8.26",
    "@angular/core": "6.0.0",
    "@angular/forms": "6.0.0",
    "@angular/common": "6.0.0",
    "@angular/router": "6.0.0",
    "@angular/compiler": "6.0.0",
    "@angular/platform-browser": "6.0.0",
    "@angular/platform-browser-dynamic": "6.0.0"
  },
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.901.1",
    "@angular/cli": "~9.1.1",
    "@angular/compiler-cli": "~9.1.1",
    "@angular/language-service": "~9.1.1",
    "@types/node": "^12.11.1",
    "@types/jasmine": "~3.5.0",
    "@types/jasminewd2": "~2.0.3",
    "codelyzer": "^5.1.2",
    "jasmine-core": "~3.5.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~4.4.1",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~2.1.0",
    "karma-jasmine": "~3.0.1",
    "karma-jasmine-html-reporter": "^1.4.2",
    "protractor": "~5.4.3",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~3.8.3"
  }
}

products.module.ts

import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { ProductsRoutingModule } from "./products-routing.module"; //Added
import { ReactiveFormsModule, FormsModule } from "@angular/forms";

@NgModule({
  imports: [
    CommonModule,
    ProductsRoutingModule,
    ReactiveFormsModule,
    FormsModule
  ],
  declarations: []
})
export class ProductsModule {}

product-list.component.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';

import { AppComponent } from './app.component';
import { ReactiveFormsModule } from "@angular/forms";


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

product-list.component.html

<h3>Product List</h3>

<form [formGroup]="myForm">
    <input type="text" formControlName="name"/>
</form>

I have imported the required modules in Lazy Loaded Module and App Module

{ ReactiveFormsModule, FormsModule } from "@angular/forms";

Any Idea about this? Is it a Bug?

https://stackblitz.com/edit/angular6-lazy-loading-gej1nn

3

3 Answers

2
votes

routing module should export RouterModule

@NgModule({
  imports: [
    RouterModule.forChild(productRoutes)
  ],
  exports: [RouterModule]
})
export class ProductsRoutingModule { }

and then ProductsModule can import ProductsRoutingModule as follow

@NgModule({
  imports: [
    CommonModule,
    ProductsRoutingModule,
    ReactiveFormsModule,
    FormsModule
  ],
  declarations: [ProductsComponent, ProductListComponent, ProductDetailComponent ]
})
export class ProductsModule {}

declarations should be provided in module which you will use in lazy loading, in this case into ProductsModule

example

updated

  1. At ProductsRoutingModule you can provide router settings, but export of RouterModule not necessary it is just a way to provide RouterModule for ProductsModule. Alternatively you can provide RouterModule in import of ProductsModule. To be able use router module declarations need to provide RouterModule in one of way.
  2. If you define declarations at ProductsRoutingModule you also should provide all dependencies in same module by import, but to make declarations be included in ProductsModule you also should export them via exports

so alternatively you can change both module like follow, you can even omit RouterModule while you have it in the main module

@NgModule({
  imports: [
    CommonModule,
    ReactiveFormsModule,
    RouterModule.forChild(productRoutes)
  ],
  declarations: [
    ProductsComponent, ProductListComponent, ProductDetailComponent
  ],
  exports: [    
    ProductsComponent, ProductListComponent, ProductDetailComponent
  ]
})
export class ProductsRoutingModule { }

@NgModule({
  imports: [
    ProductsRoutingModule
  ]
})
export class ProductsModule {}

could be interesting to read modules-in-angular and asynchronous-modules

0
votes

move component declarations in product module instead of routing module

declarations: [ProductsComponent, ProductListComponent, ProductDetailComponent ]
0
votes

I found two errors in the stackblitz code

  1. The components in the feature module should be declared in the module referenced by the parent module. In your case app.module lazyloads products.module. But the components of products module was declared in products-routing.module

  2. The router module should export the RouterModule

  3. in products.component the template string was provided inside template literal(backtik) replace it to normal string template: '<router-outlet></router-outlet>'(quotes)

find the fixed code here