16
votes

I'm migrating from AngularJS to Angular and started to use Ionic 3 (latest) to build my app.

But I have a small problem: I want to use one header on some pages with sign out function and etc. I don't want to implement it in every component page and I want to avoid duplication of code.

I tried on my own. First of all I create separate header component


header.html

<ion-header>
  <ion-navbar color="primary-light">
    <ion-title>
        Super App
    </ion-title>
    <ion-buttons end>
        <button ion-button class="button-out" icon-only (click)="signOut()">
            <ion-icon class="fa fa-sign-out"></ion-icon>
        </button>
    </ion-buttons>
  </ion-navbar>
</ion-header>

header.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'app-header',
  templateUrl: './header.html'
})
export class HeaderComponent {

    constructor(public navCtrl: NavController) {}

    signOut() {
        //some auth strategy and then
        this.navCtrl.popToRoot();
    }
}

The I go to pages where I want to add my header, I made import {HeaderComponent} from './../header/header' in page.module.ts, add HeaderComponent to declarations and entryComponents and added to page.html <app-header></app-header> and it was appeared. But when I made the same into another page - I had an error:

Failed to navigate: Type HeaderComponent is part of the declarations of 2 modules: PageOneModule and PageTwoModule! Please consider moving HeaderComponent to a higher module that imports DeliveryPageModule and PageTwoModule. You can also create a new NgModule that exports and includes HeaderComponent then import that NgModule in PageOneModule and PageTwoModule.

Then I went to app.module.ts and import header there (before I removed header from page1 and page2 modules) and I've got follow error:

Template parse errors: 'app-header' is not a known element: 1. If 'app-header' is an Angular component, then verify that it is part of this module. 2. If 'app-header' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("[ERROR ->]

I looked for examples but they are didn't work in Ionic 3. Can anybody to help with it or give a working manual how to do it?

2
Glad you want to avoid duplication, good instinct that. Generally, what you want to do is extract the header into a component. What have you tried? – Aluan Haddad
@AluanHaddad I updated my question. – Merge-pony

2 Answers

18
votes

As suggested by the error message, you want to create a shared NgModule that both declares and exports your shared header component. For example:

shared.module.ts

import {NgModule} from '@angular/core';
import {IonicPageModule} from 'ionic-angular';
import {HeaderComponent} from './header-component';

@NgModule({
  imports: [IonicPageModule.forChild(HeaderComponent)],
  declarations: [HeaderComponent],
  exports: [HeaderComponent]
}) export class SharedModule {}

Then you need to import that NgModule in all of the modules that use it.

Consuming code will have the form

page-one.module.ts

import {NgModule} from '@angular/core';
import {IonicPageModule} from 'ionic-angular';
import {SharedModule} from './shared.module';

@NgModule({
  imports: [IonicPageModule, SharedModule]      
}) export class PageOneModule {}

page-two.module.ts

import {NgModule} from '@angular/core';
import {IonicPageModule} from 'ionic-angular';
import {SharedModule} from './shared.module';

@NgModule({
  imports: [IonicPageModule, SharedModule]      
}) export class PageTwoModule {}

If you want to know why Angular punishes you for correctly following your instincts to reduce duplication by creating shared constructs, that is anyone's guess.

0
votes

Header.html

<ion-header>
<div col-12>
    <div col-1 class="iconspace togglementopmargin" float-left>
        <ion-col width-33  >
            <button class="menubutton"  block>
                <ion-icon name="md-menu" (click)="openSideMenu()"></ion-icon><br>

            </button>
        </ion-col>
    </div>
    <div col-4 class="headertitle headertitlespace" float-left>
        {{UserName}}
      
    </div>
    <div col-2 class="iconspace" float-right end (click)="gotoadd()">
        <ion-col  class="addbtn" >
            <button class="addbtn" block >
                <ion-icon name="md-add"></ion-icon><br>
            <div>    Add</div>
            </button>
        </ion-col>

    </div>
</div>

</ion-header>