Ionic 3.0: Shared Component

I’m trying to use a shared component, so it can be used in different modules, called ValidationServiceMessages but I’m getting some errors.

First I created a shared module with the component I wanted to use:

import { NgModule } from ‘@angular/core’;
import { CommonModule } from ‘@angular/common’;
import { FormsModule } from ‘@angular/forms’;
import { ValidationService } from ‘…/…/providers/validation-service’;
import { ValidationServiceMessages } from ‘./validation-service-messages’;

validation-service-messages.module.ts

@NgModule({
	declarations: [ValidationServiceMessages],
	imports: [
		CommonModule,
        FormsModule,
        ValidationService
    ],
    exports: [ValidationServiceMessages]
})
export class ValidationServiceMessagesModule { }

validation-service-messages.ts

import { Component, Input } from '@angular/core';
import { FormControl } from '@angular/forms';

@Component({
    selector: 'vs-messages',
    template: `<ion-label *ngIf="errorMessage !== null" color="{{color}}">{{errorMessage}}</ion-label>`
})
export class ValidationServiceMessages {
    @Input() control: FormControl;
    @Input() color: string;
    constructor() { }

    get errorMessage() {
        for (let propertyName in this.control.errors) {
            if (this.control.errors.hasOwnProperty(propertyName) && this.control.touched) {
                return this.getValidatorErrorMessage(propertyName, this.control.errors[propertyName]);
            }
        }
        return null;
    }

    getValidatorErrorMessage(validatorName: string, validatorValue?: any) {
        let config = {
            'required': 'Required',
            'invalidEmailAddress': 'Invalid email address',
            'invalidPassword': 'Password must be at least 8 characters long, and contain both a number and a letter.',
            'repeatField': 'teste',
            'minlength': `Minimum length ${validatorValue.requiredLength}`,
            'differentFields': 'Passwords don\'t match'
        };

        return config[validatorName];
    }
}

Then I import that shared module in a module where I want to use it.

settings.module.ts

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { SettingsPage } from './settings';
import { PipesModule } from '../../providers/pipes.module';
import { ValidationServiceMessagesModule } from '../validation-service-messages/validation-service-messages.module';

@NgModule({
	declarations: [SettingsPage],
	imports: [
		IonicPageModule.forChild(SettingsPage),
		TranslateModule.forChild(),
		PipesModule,
		ValidationServiceMessagesModule
	],
})
export class SettingsPageModule { }

settings.html

<ion-card *ngIf="showPasswordForm">
        <form [formGroup]="passwordForm" (submit)="changePassword(passwordForm)">
            <ion-list>
                <ion-item>
                    <ion-label color="primary" stacked>{{ 'settings.oldPassword' | translate }}</ion-label>
                    <ion-input type="password" formControlName="oldPassword" id="oldPassword"></ion-input>
                </ion-item>
                <div formGroupName="passwords">
                    <ion-item>
                        <ion-label color="primary" stacked>{{ 'settings.password' | translate }}</ion-label>
                        <ion-input type="password" formControlName="password" id="password"></ion-input>
                    </ion-item>
                    <ion-item>
                        <ion-label color="primary" stacked>{{ 'settings.repeatPassword' | translate }}</ion-label>
                        <ion-input type="password" formControlName="repeatPassword" id="repeatPassword"></ion-input>
                    </ion-item>
                    <ion-item>
                        <p>
                            <vs-messages color="danger" [control]="passwordForm.controls.passwords.controls.password"></vs-messages>
                            <vs-messages color="danger" [control]="passwordForm.controls.passwords"></vs-messages>
                        </p>
                    </ion-item>
                </div>
                <ion-item>
                    <button ion-button block type="submit"> {{ 'settings.changePassword' | translate }}</button>
                </ion-item>
            </ion-list>
        </form>
    </ion-card>

settings.ts

import { Component } from '@angular/core';
import { App, IonicPage, NavController, ToastController, ModalController } from 'ionic-angular';
import { UserService } from '../../providers/user-service';
import { CountryService } from '../../providers/country-service';
import { TranslateService } from '@ngx-translate/core';
import { SettingsModel } from '../../models/settings';

import { ValidationService } from '../../providers/validation-service';
import { FormBuilder, Validators } from '@angular/forms';

import { Diagnostic } from '@ionic-native/diagnostic';
import { Camera, CameraOptions } from '@ionic-native/camera';

@IonicPage()
@Component({
    selector: 'settings',
    templateUrl: 'settings.html',
    providers: [Camera, Diagnostic],
})
.
.
.

I get an error saying “template parse error” that says that ion-label (the one inside the shared component template) doesn’t recognize the color attribute.

Am I doing something wrong here?

thanks

You need to import IonicModule in ValidationServiceMessagesModule.

One other thing you might concern yourself with is that you will have multiple copies of all the code for ValidationServiceMessages in your app binary, one for each page that imports it.

Thanks man! You’re a life saver :slight_smile:.

And how would I not have that copy everywhere?

You’re probably not going to like this answer, but either wait until somebody (probably webpack) fixes the situation or give up on lazy loading for the time being and just throw everything in a monolithic app module.

Alright. I don’t think giving up the lazy loading will be better in my case, because the performance benefits I experienced are huge. Guess I’ll live with that for the time being.

Thanks!

What is the current situation regarding lazy loading - is there any timescale?

Your guess is as good as mine.

Thanks for the explanation, but I don’t understand where come from the problem, share components in a Shared Module in Angular 2/4/CLI/Webpack is possible, I used it in an application (common.chunk.js is created)