Lucio Crusca
Lucio Crusca

Reputation: 1507

How to generate a working custom component in Ionic v4?

I'm new to Ionic, I'm using v4, I'm new to Angular and I'm new to Typescript too, so please bear with me and forgive me if I ask dumb questions. I'm on Linux.

I've started a new Ionic app with

$ ionic start
[...]
Project name: comptest
Framework: Angular
Starter template: tabs
[...]

Then I tried it:

$ cd comptest
$ ionic serve -l
[...]
? Install @ionic/lab? Yes
[...]

the browser opened up and the app worked ok. Then I tried to generate a new custom component:

$ ionic generate component mySpan1
[...]
[OK] Generated component!

That created my-span1-component.ts among others, which contains:

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

@Component({
  selector: 'my-span1',
  templateUrl: './my-span1.component.html',
  styleUrls: ['./my-span1.component.scss'],
})
export class MySpan1Component {

  constructor() { }

}

Please note that I edited the selector and made it look just my-span1 instead of the default app-my-span1, but I didn't touch anything else, not even the html <p> tag that in future will become a <span> instead for obvious reasons. Then I tried to use <my-span1> in tab1 page, so I edited tab1.page.html and added <my-span1> tag:

<ion-content>
    <my-span1></my-span1> <!-- This is my edit -->
    <ion-card class="welcome-card">
      <img src="/assets/shapes.svg" alt="" /> 
        [...]

After that edit the page stopped working. In the browser console I'm getting this error:

'my-span1' is not a known element

Googling that I found this other SO question: Ionic 4 cannot import custom component is not a know element

but the accepted answer is quite poor to say the least, and when it comes down to creating a new module I enter the unknown (for me) territory. Anyway, I tried ionic generate module components, and it worked, then I declared MySpan1Component in that new module:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MySpan1Component } from '../my-span1/my-span1.component';

@NgModule({
  declarations: [
    MySpan1Component
  ],
  imports: [
    CommonModule,
  ]
})
export class ComponentsModule { }

Then I imported the new module into the app module, like this:

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 { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ComponentsModule } from './components/components.module';

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

but I still get the same error in the console, e.g. 'my-span1' is not a known element. And I don't know what to do next.

Another question I've found here suggests the same solution, or to add my component to the exports array: tried that too, but no luck (same error in the console):

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 { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
//import { ComponentsModule } from './components/components.module';
import { MySpan1Component } from './my-span1/my-span1.component';

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

What am I missing in my code that would make my-span1 work?

Upvotes: 3

Views: 2128

Answers (1)

Sergey Rudenko
Sergey Rudenko

Reputation: 9227

You were on the right track:

  • create new app: ionic start my-new-app
  • generate new component: ionic generate my-span1
  • add it to your tab1.page.module as import + add to declarations

Like so:

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

import { MySpan1CompComponent } from '../my-span1-comp/my-span1-comp.component'; // add this import statement to the module within which you intend to use your new component

@NgModule({
  imports: [
    IonicModule,
    CommonModule,
    FormsModule,
    RouterModule.forChild([{ path: '', component: Tab1Page }])
  ],
  declarations: [Tab1Page, MySpan1CompComponent] // add your component in here 
})
export class Tab1PageModule {}

Upvotes: 2

Related Questions