Search code examples
angularangular-module

Angular: Shared Module not finding dependent class used in Input() Property


I recently refactored a small application into modules. I'm running into problems with components getting declared more than once, so I factored out those duplicates into a shared module.

For the most part this works but I have one component that I can't get to load.

I get the following error:

ERROR in Template parse errors: Can't bind to 'error' since it isn't a known property of 'error-display'. 1. If 'error-display' is an Angular component and it has 'error' input, then verify that it is part of this module.

The component looks like this:

import {Component, OnInit, Input} from '@angular/core';
import {Response} from "@angular/http";
import {Observable} from "rxjs";

@Component({
  selector: 'error-display',
  //templateUrl: 'errorDisplay.html'
  template:  `
      <div *ngIf="error.message"
           class="alert alert-{{error.icon}} alert-dismissable">
          <button *ngIf="error.dismissable" type="button" class="close"
                  data-dismiss="alert" aria-hidden="true">
              <i class="fa fa-remove"></i>
          </button>

          <div *ngIf="error.header" style="font-size: 1.5em; font-weight: bold">
              <i class="fa fa-{{error.imageIcon}}" style="color: {{error.iconColor}}"></i>
              {{error.header}}
          </div>
          <i *ngIf="!error.header"
             class="fa fa-{{error.imageIcon}}"
             style="color: {{error.iconColor}}"></i>

          <strong>{{error.message}}</strong>
      </div>
  `
})

export class ErrorDisplay {
  constructor() {
  }

  // *** THIS IS THE PROBLEM PROPERTY ***
  @Input() error: ErrorInfo = new ErrorInfo();
}


// @Injectable()
export class ErrorInfo {
  constructor() {
    this.reset();
  }

  message:string;
  icon:string;
  dismissable:boolean;
  header:string;
  imageIcon:string;
  iconColor:string;
  timeout: number;    
  response:Response = null;    
  ...
}

The error suggests that the component is not registered at the module level, but it is registered in my shared module;

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import {ErrorDisplay, ErrorInfo} from "./error-display/errorDisplay";
import {AppConfiguration} from "./appConfiguration";

@NgModule({
  providers: [
    AppConfiguration,
    ErrorInfo
  ],
  imports: [
    CommonModule
  ],
  declarations: [
    ErrorDisplay
  ]
})
export class SharedModule { }

The shared module is then imported in the App Module:

imports: [
    ...
    SharedModule,
    UserAuthenticationModule,
    UserAdministrationModule,
    ...
],

The individual pages that are using the component also explicitly reference the component and the embedded class:

import { Component, OnInit } from '@angular/core';
import {ErrorInfo} from "../../shared/error-display/errorDisplay";


@Component({
    selector: 'signin',
    templateUrl: './signin.html'
})
export class SignInComponent implements OnInit {

    error: ErrorInfo = new ErrorInfo();

    ...
}

It looks to me that the component is referenced in the right place in the shared module with declarations: [ErrorDisplay].

This code worked fine when everything was part of the main app module. But as part of the shared module I can't get this to work.

I've tried adding ErrorInfo as a service and adding as a provider, but that doesn't fix it. If I add ErrorDisplay as a declared component to another module I get:

ype ErrorDisplay is part of the declarations of 2 modules: SharedModule and UserAuthenticationModule! Please consider moving ErrorDisplay to a higher module that imports SharedModule and UserAuthenticationModule.

which is exactly what I am doing in the first place.

It looks like I somehow need to declare the ErrorInfo class (it's not really a service as it's just created internally by a component that uses it, but I don't know

What am I missing?


Solution

  • The problem appears to be that you haven't exported error-display so the app doesn't know what it is, let alone its error input.

    So add it like:

    exports: [ErrorDisplay]
    

    in your SharedModule and it should work.