Handling component declarations


#1

Hello, I have some problem probably with understanding of components.
I thought, we build components to prevent same pieces of code on multiple pages.

Now, for example I created a component Quote, that should be represented by ion-card.
quote.ts (QuoteModel is only a container class to hold properties of every Quote)

@Component({
  selector: 'quote',
  templateUrl: 'quote.html'
})
export class QuoteComponent { 

  @Input('quoteObj') quoteObj :QuoteModel;

  quote: QuoteModel;

  constructor() {
    //console.log('Hello QuoteComponent Component');
  }

  ngAfterViewInit() {
    this.quote = this.quoteObj;
  }

}

quote.html

<ion-card color="primDark">
  <ion-card-content>
    <p class="quote-text ma-centered">{{ quoteObj.text }}</p>
    <div class="action-icons ma-centered">
      <button ion-button color="primDark"><ion-icon name="share"></ion-icon></button>
      <button ion-button color="primDark"><ion-icon name="image"></ion-icon></button>
      <button ion-button color="primDark"><ion-icon name="star"></ion-icon></button>
    </div>
  </ion-card-content>
</ion-card>

I want to use this component on multiple pages. So when I use it for example on ProfilePage and QuotesPage, where should I declare QuoteComponent to prevent errors?

When I add QuoteComponent to declarations only in app.module.ts (in imports I have ProfilePageModule and QuotesPageModule) and use in profile.html, I get this error:

Uncaught Error: Template parse errors:
‘quote’ is not a known element

When I delete this declaration from app.module.ts and add QuoteComponent in profile.module.ts declarations array, it works fine. But when I do the same thing for my second page (add QuoteComponent to quotes.module.ts), it fails with this error:

Uncaught Error: Type QuoteComponent is part of the declarations of 2 modules: ProfilePageModule and QuotesPageModule! Please consider moving QuoteComponent to a higher module that imports ProfilePageModule and QuotesPageModule. You can also create a new NgModule that exports and includes QuoteComponent then import that NgModule in ProfilePageModule and QuotesPageModule.

Is there any clear way to handle this? Thanks in advance


#2

Hello,
I hope I understood it right. You make your custom component, call it mycom.
The custom component is decared in one ngmodule. If you are lazyloading, then you have a file called mycom.module.ts. with something like

import { NgModule } from '@angular/core';
import { IonicModule } from 'ionic-angular';
import { MycomComponent } from './mycom';

@NgModule({
  declarations: [
    MycomComponent,
  ],
  imports: [
    IonicModule,
  ],
  exports: [
    MycomComponent
  ]
})
export class MycomComponentModule {}

If you want to use this mycom in an other htnl file, you must import it in module file. For lazy loading for example in whatever.module.ts.

In whatever.module.ts you have an import (exactly match of upperLowerCase like

import { MyComModule } from '../??/mycom/mycom.module';

Also you must add to imports array

imports: [
        MycomModule,
    IonicPageModule.forChild(Kapitel99Bis999Page)
  ],

Now you can use it in html like

<mycomponent></mycomponent>

If you need mycom in .ts file for example you fetch it with @Viewchild you must import it like

import { MyCom } from '../??/mycom/mycom';

Best regards, anna-liebt


#3

Thanks for your answer, I still have error after ionic serve.

I only changed Mycom to Quotes, so I created file quotes.module.ts in quote component directory (i have quotes.html, quotes.scss, quotes.ts and quotes.module.ts files in one folder under components).

my quote.module.ts looks like yours:

import { NgModule } from '@angular/core';
import { IonicModule } from 'ionic-angular';
import { QuoteComponent } from './quote';

@NgModule({
  declarations: [
    QuoteComponent,
  ],
  imports: [
    IonicModule,
  ],
  exports: [
    QuoteComponent
  ]
})
export class QuoteComponentModule {}

QuoteComponent looks exacly same as before. In app.module.ts is nothing about QuoteComponent or QuoteComponentModule (not even imported on the top, no declared or imported in @NgModule arrays)

In ProfilePage in profile.module.ts file I have this and it works fine on one page.

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { ProfilePage } from './profile';
import { QuoteComponentModule } from '../../components/quote/quote.module';

@NgModule({
  declarations: [
    ProfilePage
  ],
  imports: [
    IonicPageModule.forChild(ProfilePage),
    QuoteComponentModule
  ]
})
export class ProfilePageModule {}

But when I do exactly the same on another page (like QuotesPage):

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { QuotesPage } from './quotes';
import { QuoteComponentModule } from '../../components/quote/quote.module';

@NgModule({
  declarations: [
    QuotesPage
  ],
  imports: [
    IonicPageModule.forChild(QuotesPage),
    QuoteComponentModule
  ],
})
export class QuotesPageModule {}

It fails again with this error:

Uncaught Error: Type QuoteComponent is part of the declarations of 2 modules: QuoteComponentModule and AppModule! Please consider moving QuoteComponent to a higher module that imports QuoteComponentModule and AppModule. You can also create a new NgModule that exports and includes QuoteComponent then import that NgModule in QuoteComponentModule and AppModule.

That’s the reason Im struggling here for all day long.


#4

Hello,
If you are sure that every thing is fine, because you didn’t posted app.module.ts, then stopp ionic serve, delete content of www folder and content of .sourcemaps and do ionic serve again.

Best regards, anna-liebt


#5

Hello,

also check if you have a component.module.ts. And there is a declaration inside ngmodule.

Best regards, anna-liebt


#6

Hello,
I am again. Also clear browser cache.

Best regards, anna-liebt


#7

Thank you, deleting www folder helped :slight_smile:

Also, what is component.module.ts for? This file generated but I deleted it later because of no use for me. When you import this multi-component module, you still can’t use separate modules, right?


#8

Another thing you might consider is completely ditching lazy loading, which will significantly reduce confusing boilerplate code and (unless webpack has improved this while I wasn’t paying attention) make your app binary smaller as well by eliminating duplicated code for your quote component.


#9

Hello,

fine that deleting helped. This is really a mess, special for bigger apps with more pages it seems a %$%§%& standard.

I am a beginner in ionic, so maybe somebody can correct me. In app.module.ts you have eager loading, in whatever.componet.ts you have lazy loading and in component.module.ts (I do not use it) you have a kind of central place for lazy loading.

Best regards, anna-liebt