Generating components from CLI

I’m having trouble using a component generated in ionic 3 through

ionic generate component test

The generator creates test.component.ts:

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

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

  constructor() { }

  ngOnInit() {
  }

}

app.module.ts:

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

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

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

@NgModule({
  declarations: [AppComponent, TestComponent],
  entryComponents: [],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

However, I can’t use the component in home.page.html (part of the default app):

<ion-content padding>
  The world is your oyster.  
  <p>If you get lost, the
    <a target="_blank" rel="noopener" href="https://ionicframework.com/docs">docs</a> will be your guide.</p>
  <app-test></app-test>
</ion-content>

The browser generates the following error in the console:

ERROR Error: Uncaught (in promise): Error: Template parse errors:
'app-test' is not a known element:
1. If 'app-test' is an Angular component, then verify that it is part of this module.
2. If 'app-test' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("t="_blank" rel="noopener" href="https://ionicframework.com/docs">docs</a> will be your guide.</p>
  [ERROR ->]<app-test></app-test>
</ion-content>

I’ve tried variations of importing the component in home.page.ts and home.module.ts. For example, in home.module.ts:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { RouterModule } from '@angular/router';
import { HomePage } from './home.page';
import { TestComponent } from '../test/test.component';
@NgModule({
  imports: [
    TestComponent,
    CommonModule,
    FormsModule,
    IonicModule,
    RouterModule.forChild([
      {
        path: '',
        component: HomePage
      }
    ])
  ],
  declarations: [HomePage]
})
export class HomePageModule {}

What is the intended way for new components generated through the CLI to be used?

1 Like

Answered my own question, in case anybody has similar issues and has trouble finding documentation on this.

ionic generate component creates the necessary components and inserts them into app.module.ts. However, this is not sufficient for using in any page that is part of an ionic project. The directive only seems to be recognized in app.component.html. In home.module.ts, adding the TestComponent also seems to fail due to it be declared in both app.module.ts and home.module.ts. The answer is to do the following:

Create test.component.module.ts:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule } from '@ionic/angular';

import { TestComponent } from './test.component';

@NgModule({
  imports: [
    CommonModule,
    IonicModule,
  ],
  declarations: [TestComponent],
  exports: [TestComponent]
})
export class TestComponentModule {}

Then in home.module.ts, import TestComponentModule and include it in the NgModule imports:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { RouterModule } from '@angular/router';

import { HomePage } from './home.page';
import { TestComponentModule } from '../test/test.component.module';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    RouterModule.forChild([
      {
        path: '',
        component: HomePage
      }
    ]),
    TestComponentModule
  ],
  declarations: [HomePage]
})
export class HomePageModule {}
7 Likes

Thank you for your comment! Annoying how this isn’t documented anywhere.

Thank you so much for this! The ionic team should really document this somewhere.
P.S. Along with the instructions you gave, I had to add the TestComponent to the declarations array in app-module.ts

1 Like

I still didn’t see this in Ionic documentation anywhere.

Today I learned (TIL):
⁃ To use an Ionic component that doesn’t have a module (the default), import it to the page you want to use it on, then add it to that page’s module file’s declarations.

Unless you have a very large app, I am still not convinced that lazy loading provides a net win. So another option is to have only one module (AppModule) in your entire app, manage everything in there, greatly reduce the amount of boilerplate garbage in your app and the time you spend managing module dependencies. That’s what I do.

1 Like