Template context for Angular components and RouterModule

31 Views Asked by At

I'm learning Angular and trying to understand how RouterModule works with other modules. Say I have a simple AppModule as follows.

import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";
import { RouterModule, Routes } from "@angular/router";
import { MainComponent } from "./main/main.component";
import { FeatureComponent } from "./feature/feature.component";

const routes: Routes = [
  {
    path: "",
    component: MainComponent,
  },
  {
    path: "feature",
    component: FeatureComponent,
  },
];

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, RouterModule.forRoot(routes)],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

Neither MainComponent or FeatureComponent are declared in the declarations property of any AppModule but this code still works. What's going on here?

I'm reading this article about template contexts in Angular. So in this case am I correct in understanding that these components don't have a template context since they are not declared in any module and thus will only be able to support standard HTML/CSS/JS and not the typical features you would get in an Angular component?

Now say I want to create a WidgetComponent that in used in both MainComponent and FeatureComponent. If I just add WidgetComponent to the declarations of AppModule I get an error in the other components saying "app-widget is not a known element".

@NgModule({
  declarations: [AppComponent, WidgetComponent],
  imports: [BrowserModule, RouterModule.forRoot(routes)],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

'app-widget' is not a known element:

  1. If 'app-widget' is an Angular component, then verify that it is part of this module.
  2. If 'app-widget' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.

This makes sense as neither MainComponent or FeatureComponent are declared in AppModule where WidgetComponent is declared so again they are not in the same template context. Is my understanding of this correct?

To fix this I can declare all three components in AppModule.

@NgModule({
  declarations: [
    AppComponent,
    WidgetComponent,
    MainComponent,
    FeatureComponent,
  ],
  imports: [BrowserModule, RouterModule.forRoot(routes)],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

...or create a separate modules for the components and import them into one another.

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

@NgModule({
  declarations: [MainComponent],
  imports: [CommonModule, WidgetModule],
})
export class MainModule {}

@NgModule({
  declarations: [FeatureComponent],
  imports: [CommonModule, WidgetModule],
})
export class FeatureModule{}

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, RouterModule.forRoot(routes)],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

But in this 2nd solution I don't need to import any of the other modules into AppModule I can simply pass the component classes directly to the RouterModule. So what I understand from this is the template context of a component is defined simply by the module where it is declared. Is that right?

0

There are 0 best solutions below