Balaji
Balaji

Reputation: 125

Using Angular Components declared on same module in one another

Say we have a component A declared in module M and another component B declared in same module M. Can we call Component B in component A, through its selector ?

I have done something like this in previous versions of Angular to be precise in Angular 6.

But i get the error

NG8001: 'B' is not a known element

in Angular 11

Following is the folder structure

app
-home
-- home-footer.component.html
-- home-footer.component.ts
-- home.component.html
-- home.component.less
-- home.component.spec.ts
-- home.component.ts
-- home.module.ts
app-routing.module.ts
app.component.html
app.component.less
app.component.spec.ts
app.component.ts
app.module.ts

app.module.ts

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

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

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

app-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';

const routes: Routes = [{
  path: "",
  component: HomeComponent
}];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

home.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HomeFooterComponent } from './home-footer.component';
import { HomeComponent } from './home.component';



@NgModule({
  declarations: [HomeComponent, HomeFooterComponent],
  imports: [
    CommonModule
  ]
})
export class HomeModule { }

home.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.less']
})
export class HomeComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}

home-footer.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home-footer',
  templateUrl: './home-footer.component.html'
})
export class HomeFooterComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}

home.component.html

<p>home works!</p>
<app-home-footer></app-home-footer>

home-footer.component.html

<span>Home Footer works</span>

Error Message

√ Browser application bundle generation complete.

    Error: home/home.component.html:2:1 - error NG8001: 'app-home-footer' is not a known element:
    1. If 'app-home-footer' is an Angular component, then verify that it is part of this module.
    2. If 'app-home-footer' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
    
    2 <app-home-footer></app-home-footer>
      ~~~~~~~~~~~~~~~~~
    
      home/home.component.ts:5:16
        5   templateUrl: './home.component.html',
                         ~~~~~~~~~~~~~~~~~~~~~~~
        Error occurs in the template of component HomeComponent.

Version Information :

ng --version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 11.1.1
Node: 10.16.3
OS: win32 x64

Angular: 11.1.0
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1101.1
@angular-devkit/build-angular   0.1101.1
@angular-devkit/core            11.1.1
@angular-devkit/schematics      11.1.1
@angular/cli                    11.1.1
@schematics/angular             11.1.1
@schematics/update              0.1101.1
rxjs                            6.6.3
typescript                      4.1.3

Upvotes: 0

Views: 2893

Answers (2)

Timothy
Timothy

Reputation: 3593

You need to add HomeModule into AppModule if you wanna use its components there. Also keep in mind that module exports array supposed to contain used components, directives, modules.

@NgModule({
  declarations: [HomeComponent, HomeFooterComponent],
  imports: [
    CommonModule
  ],
  export: [HomeComponent, HomeFooterComponent] // Add here declarations and/or imports which should be used my AppModule
})
export class HomeModule { }

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    HomeModule, // Add HomeModule here
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

But in this case App module bundle will contain both modules (so its gonna be bigger in size).

The second solution - is use lazy loading. But you already did it.

Upvotes: 3

Balaji
Balaji

Reputation: 125

Adding the lazy loading details for the Home Component route fixes the issue. Without lazy load the components registered to the HomeModule were not part of the main chunk generated by webpack.

In app-routing.module.ts

const routes: Routes = [{
  path: "home",
  component: HomeComponent,
  loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
}];

Upvotes: 0

Related Questions