Problem adding a custom component to ionic 4

#1

I am using the command:

ionic generate component accordion-list

Then the following directory structure is created automatically:

components
-accordion-list
–accordion-list.html
–accordion-list.scss
–accordion-list.ts
components.module

So I’m trying to make a hello world with my custom component on any html page, like this:

It already includes and excludes entries for my custom component in the files: “app \ app.component.ts” and “app \ app.module.ts”.

However, I still get the following error on the console:

-------------------- Error --------------------
ERROR Error: Uncaught (in promise): Error:
Template parse errors:
‘accordion-list’ is not a known element:

  1. If ‘accordion-list’ is an Angular component, then verify that it is part of this module.

  2. If ‘accordion-list’ is a Web Component then add ‘CUSTOM_ELEMENTS_SCHEMA’ to the ‘@NgModule.schemas’ of this component to suppress this message. ("

[ERROR ->]
-------------------- Error --------------------

---------------- My Environment --------------------

Angular CLI: 7.3.2
Node: 8.11.2
OS: win32 x64
Angular: 5.2.10
… animations, common, compiler, compiler-cli, core, forms
… http, platform-browser, platform-browser-dynamic

Package Version

@angular-devkit/architect 0.13.2 (cli-only)
@angular-devkit/build-optimizer 0.0.35
@angular-devkit/cor 7.3.2 (cli-only)
@angular-devkit/schematics 7.3.2 (cli-only)
@schematics/angular 7.3.2 (cli-only)
@schematics/update 0.13.2 (cli-only)
rxjs 5.5.11
typescript 2.6.2
webpack 3.8.1

Ionic 4.10.3
---------------- My Environment --------------------

----------------- My questions --------------------

What are the correct locations for referencing my custom components?

Sorry for the outburst. But for what reason the command “ionic generate component …” does not make the necessary entries. Would not it be more intuitive?
----------------- My questions --------------------

#2

Hi @silvairsoares :wave:

Can you share the module.ts of the page that is using the <accordion-list> component? I think it’s called ClientePageModule.

Best,
Rodrigo

1 Like
#3

cliente.html:

<ion-header>
	<ion-navbar>
		<ion-title>{{str?.Cliente?.Titulo}}</ion-title>
	</ion-navbar>
</ion-header>
<ion-content padding>
	<ion-item>
		<ion-label floating>{{translatorProvider.str?.Cliente?.Nome}}</ion-label>
		<ion-input (keyup.enter)="FocusDescricao()" type="text" min="1" [value]="model.nome" [(ngModel)]="model.nome"></ion-input>
	</ion-item>
	<ion-item>
		<ion-label floating>{{translatorProvider.str?.Cliente?.Telefone}}</ion-label>
		<ion-input (keyup.enter)="FocusDescricao()" type="text" min="1" [value]="model.telefone" [(ngModel)]="model.telefone"></ion-input>
	</ion-item>
	<ion-item>
		<ion-label floating>{{translatorProvider.str?.Cliente?.Celular}}</ion-label>
		<ion-input (keyup.enter)="FocusDescricao()" type="text" min="1" [value]="model.celular" [(ngModel)]="model.celular"></ion-input>
	</ion-item>

	<accordion-list>
	</accordion-list>
	
	<button ion-button block (click)="save()">{{translatorProvider.str?.Geral?.Salvar}}</button>
</ion-content>

cliente.ts:

import { ClienteModel } from './../../model/ClienteModel';
import { ClienteProvider } from '../../providers/cliente/ClienteProvider';
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams, ToastController } from 'ionic-angular';

import { Storage } from '@ionic/storage';
import { TranslatorProvider } from '../../providers/translator/translator';

@IonicPage()
@Component({
  selector: 'page-cliente',
  templateUrl: 'cliente.html',
})
export class ClientePage {

  model: ClienteModel;
  public str: any;


  constructor(public translatorProvider: TranslatorProvider, public navCtrl: NavController, public navParams: NavParams, private toast: ToastController, private clienteProvider: ClienteProvider, public storage: Storage) {

	this.model = new ClienteModel();

	if (this.navParams.data.id) {
	  this.clienteProvider.get(this.navParams.data.id)
		.then((result: any) => {
		  this.model = result;
		})
	}

  }

  ionViewDidEnter() {
	this.str = this.translatorProvider.str;
  }

  save() {
	this.saveCliente()
	  .then(() => {
		this.toast.create({ message: this.str.Cliente.MsgSalvarSucesso, duration: 3000, position: 'botton' }).present();
		this.navCtrl.pop();
	  })
	  .catch(() => {
		this.toast.create({ message: this.str.Cliente.MsgSalvarErro, duration: 3000, position: 'botton' }).present();
	  })
  }

  private saveCliente() {
	if (this.model.id) {
	  return this.clienteProvider.update(this.model);
	} else {
	  return this.clienteProvider.insert(this.model);
	}
  }
}

cliente.module.ts

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { ClientePage } from './cliente';

@NgModule({
  declarations: [
	ClientePage,
  ],
  imports: [
	IonicPageModule.forChild(ClientePage),
  ],
})
export class ClientePageModule {}
#4

@silvairsoares The accordion list is in the template (HTML) of ClientePage, so you need to import in the ClientePageModule the module that declares and exports AccordionListComponent.

If you use the approach of 1 module per component (which I recommend), you would have a module AccordionListComponentModule that have AccordionListComponent in its declaration and exports it, then you could make your ClientePageModule as:

@NgModule({
  declarations: [
	ClientePage,
  ],
  imports: [
	AccordionListComponentModule,
	IonicPageModule.forChild(ClientePage),
  ],
})
export class ClientePageModule {}

If you import all your components in a ComponentsModule (which I don’t recommend), then you could make your ClientePageModule as:

@NgModule({
  declarations: [
	ClientePage,
  ],
  imports: [
	ComponentsModule,
	IonicPageModule.forChild(ClientePage),
  ],
})
export class ClientePageModule {}
1 Like
#5

I can hardly believe it worked. Thank you very much @lucasbasquerotto. I spent hours working with this seemingly simple problem.

Exactly what you said.

I created a new module only for the “accordion-list” component with the following content:

import { NgModule} from '@angular/core';
import { AccordionListComponent } from './accordion-list';

@NgModule({
  declarations: [
	AccordionListComponent
  ],
  exports: [
	AccordionListComponent
  ]
})
export class AccordionListComponentModule {
}

And I imported it where I’d like to use it (ClientPageModule). Staying like this:

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { ClientePage } from './cliente';
import { AccordionListComponentModule } from '../../components/accordion-list/accordion-list.component.module';

@NgModule({
  declarations: [
	ClientePage,
  ],
  imports: [
	IonicPageModule.forChild(ClientePage),
	AccordionListComponentModule
  ],
})
export class ClientePageModule {}

I am adding images to serve others who are in the same situation as mine.

1 Like
#6

I use Ionic 4 and have the same issue but I can’t solve it in my current Project, it works very well on new blank project…
I can’t find where is the issue???

any suggestion or help will be appreciated.

#7

Hello,
the issue of initial question is marked as solution.
If this is not working for you then you have maybe a different problem.
If you want hepl, then you should provide more specific information to your problem.

Best reagrds, anna-liebt