[angular] CUSTOM_ELEMENTS_SCHEMA added to NgModule.schemas still showing Error

I just upgraded from Angular 2 rc4 to rc6 and having troubles doing so.

I see the following error on my console:

Unhandled Promise rejection: Template parse errors:
'cl-header' is not a known element:
1. If 'cl-header' is an Angular component, then verify that it is part of this module.
2. If 'cl-header' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schema' of this component to suppress this message. ("<main>
    [ERROR ->]<cl-header>Loading Header...</cl-header>
    <div class="container-fluid">
      <cl-feedbackcontai"): AppComponent@1:4

Here is my Header Component:

import { Component } from '@angular/core';
import { Router } from '@angular/router';

// own service
import { AuthenticationService } from '../../../services/authentication/authentication.service.ts';

import '../../../../../public/css/styles.css';

@Component({
  selector: 'cl-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent { // more code here... }

Here is my Header Module:

import { NgModule, CUSTOM_ELEMENTS_SCHEMA }      from '@angular/core';
import { RouterModule } from '@angular/router';
import { CommonModule }      from '@angular/common';
import { FormsModule }      from '@angular/forms';

import { HeaderComponent }  from './../../../components/util_components/header/header.component.ts';

@NgModule({
    declarations: [ HeaderComponent ],
    bootstrap:    [ HeaderComponent ],
    imports: [ RouterModule, CommonModule, FormsModule ],
    schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
})
export class HeaderModule { }

I created a wrapper module called util module which imports the HeaderModule:

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

import {HeaderModule} from "./header/header.module";
// ...

@NgModule({
    declarations: [ ],
    bootstrap:    [ ],
    imports: [ HeaderModule]
})
export class UtilModule { }

Which is finally imported by the AppModule:

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

import { BrowserModule } from '@angular/platform-browser';

import { AppComponent }  from './app.component';

import {UtilModule} from "./modules/util_modules/util.module";
import {RoutingModule} from "./modules/routing_modules/routing.module";

@NgModule({
    bootstrap: [AppComponent],
    declarations: [AppComponent],
    imports: [BrowserModule, UtilModule, RoutingModule]
})
export class AppModule { }

To my understanding I am following the instructions of the error message using the SCHEMA to surpress the error. But it seems not to work. What am I doing wrong? (I hope its nothing obvious I just don't see at the moment. Been spending the past 6 hours upgrading to this version...)

This question is related to angular karma-jasmine

The answer is


Just wanted to add a little bit more on this.

With the new angular 2.0.0 final release (sept 14, 2016), if you use custom html tags then it will report that Template parse errors. A custom tag is a tag you use in your HTML that's not one of these tags.

It looks like the line schemas: [ CUSTOM_ELEMENTS_SCHEMA ] need to be added to each component where you are using custom HTML tags.

EDIT: The schemas declaration needs to be in a @NgModule decorator. The example below shows a custom module with a custom component CustomComponent which allows any html tag in the html template for that one component.

custom.module.ts

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

import { CustomComponent } from './custom.component';

@NgModule({
  declarations: [ CustomComponent ],
  exports: [ CustomComponent ],
  imports: [ CommonModule ],
  schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
})
export class CustomModule {}

custom.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'my-custom-component',
  templateUrl: 'custom.component.html'
})
export class CustomComponent implements OnInit {
  constructor () {}
  ngOnInit () {}
}

custom.component.html

In here you can use any HTML tag you want.

<div class="container">
  <boogey-man></boogey-man>
  <my-minion class="one-eyed">
    <job class="plumber"></job>
  </my-minion>
</div>

solved this problem in the /app/app.module.ts file

import your component and declare it

import { MyComponent } from './home-about-me/my.component';

@NgModule({
  declarations: [
    MyComponent,
  ]

That didn't work for me (using 2.0.0). What worked for me was importing RouterTestingModule instead.

I resolved this by importing RouterTestingModule in spec file.

import {
    RouterTestingModule
} from '@angular/router/testing';

  beforeEach(() => {

        TestBed.configureTestingModule({
            providers: [
                App,
                AppState,
                Renderer,
                {provide: Router,  useClass: MockRouter }
            ],
            imports: [ RouterTestingModule ]
        });

    });

This is rather long post and it gives a more detailed explanation of the issue.

The problem (in my case) comes when you have Multi Slot Content Projection

See also content projection for more info.

For example If you have a component which looks like this:

html file:

 <div>
  <span>
    <ng-content select="my-component-header">
      <!-- optional header slot here -->
    </ng-content>
  </span>

  <div class="my-component-content">
    <ng-content>
      <!-- content slot here -->
    </ng-content>
  </div>
</div>

ts file:

@Component({
  selector: 'my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.scss'],
})
export class MyComponent {    
}

And you want to use it like:

<my-component>
  <my-component-header>
    <!-- this is optional --> 
    <p>html content here</p>
  </my-component-header>


  <p>blabla content</p>
  <!-- other html -->
</my-component>

And then you get template parse errors that is not a known Angular component and the matter of fact it isn't - it is just a reference to an ng-content in your component:

And then the simplest fix is adding

schemas: [
    CUSTOM_ELEMENTS_SCHEMA
],

... to your app.module.ts


But there is an easy and clean approach to this problem - instead of using <my-component-header> to insert html in the slot there - you can use a class name for this task like this:

html file:

 <div>
  <span>
    <ng-content select=".my-component-header">  // <--- Look Here :)
      <!-- optional header slot here -->
    </ng-content>
  </span>

  <div class="my-component-content">
    <ng-content>
      <!-- content slot here -->
    </ng-content>
  </div>
</div>

And you want to use it like:

<my-component>
  <span class="my-component-header">  // <--- Look Here :) 
     <!-- this is optional --> 
    <p>html content here</p>
  </span>


  <p>blabla content</p>
  <!-- other html -->
</my-component>

So ... no more components that do not exist so there are no problems in that, no errors, no need for CUSTOM_ELEMENTS_SCHEMA in app.module.ts

So If You were like me and did not want to add CUSTOM_ELEMENTS_SCHEMA to the module - using your component this way does not generates errors and is more clear.

For more info about this issue - https://github.com/angular/angular/issues/11251

For more info about Angular content projection - https://blog.angular-university.io/angular-ng-content/

You can see also https://scotch.io/tutorials/angular-2-transclusion-using-ng-content


I'd like to add one additional piece of information since the accepted answer above didn't fix my errors completely.

In my scenario, I have a parent component, which holds a child component. And that child component also contains another component.

So, my parent component's spec file need to have the declaration of the child component, AS WELL AS THE CHILD'S CHILD COMPONENT. That finally fixed the issue for me.


Just read this post and according to the angular 2 docs:

export CUSTOM_ELEMENTS_SCHEMA
Defines a schema that will allow:

any non-Angular elements with a - in their name,
any properties on elements with a - in their name which is the common rule for custom elements.

So just in case anyone runs into this problem, once you have added CUSTOM_ELEMENTS_SCHEMA to your NgModule, make sure that whatever new custom element you use has a 'dash' in its name eg. or etc.


I think you are using a custom module. You can try the following. You need to add the following to the file your-module.module.ts:

import { GridModule } from '@progress/kendo-angular-grid';
@NgModule({
  declarations: [ ],
  imports: [ CommonModule, GridModule ],
  exports: [ ],
})

util.component.ts

@Component({
    selector: 'app-logout',
    template: `<button class="btn btn-primary"(click)="logout()">Logout</button>`
})
export class LogoutComponent{}

util.module.ts

@NgModule({
    imports: [...],
    exports: [
        LogoutComponent
    ],
    declarations: [LogoutComponent]
})
export class AccountModule{};

LogoutComponent Needs to be exported

dashboard.module.ts
import AccountModule in module where we want to use <app-logout> import { AccountModule } from 'util.module';

@NgModule({
  imports: [
    CommonModule, AccountModule
  ],
  declarations: [DashboardComponent]
})
export class DashboardModule { }

dashboard.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-dashboard',
  template: `<div><app-logout></app-logout></div>`
})
export class DashboardComponent implements OnInit {
  constructor() {}
  ngOnInit() {}
}

I am not required to import and use CUSTOM_ELEMENTS_SCHEMA.
however its not working when dashboard.module is lazy loaded.
When using CUSTOM_ELEMENTS_SCHEMA in case of lazy loading, error is suppressed but the component is not added to dom.


This can also come up when running unit tests if you are testing a component with custom elements. In that case custom_elements_schema needs to be added to the testingModule that gets setup at the beginning of the .spec.ts file for that component. Here is an example of how the header.component.spec.ts setup would begin:

import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

describe('HeaderComponent', () => {
  let component: HeaderComponent;
  let fixture: ComponentFixture<HeaderComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [PrizeAddComponent],
      schemas: [
        CUSTOM_ELEMENTS_SCHEMA
      ],
    })
      .compileComponents();
  }));

Make sure to import component in declarations array

@NgModule({
  declarations: [ExampleComponent],
  imports: [
      CommonModule,
      ExampleRoutingModule,
      ReactiveFormsModule
  ]
})

Did you use the webpack... if yes please install

angular2-template-loader

and put it

test: /\.ts$/,
   loaders: ['awesome-typescript-loader', 'angular2-template-loader']

It didn't work for me either. I changed

CUSTOM_ELEMENTS_SCHEMA

for

NO_ERRORS_SCHEMA

which was suggested in this article: https://scotch.io/tutorials/angular-2-transclusion-using-ng-content

Now it works.


For me, I needed to look at :

1. If 'cl-header' is an Angular component, then verify that it is part of this module.

This means that your component isn't included in the app.module.ts. Make sure it's imported and then included in the declarations section.

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

import { BrowserModule } from '@angular/platform-browser';

import { AppComponent }  from './app.component';

import { UtilModule } from "./modules/util_modules/util.module";
import { RoutingModule } from "./modules/routing_modules/routing.module";

import { HeaderComponent } from "./app/components/header.component";

@NgModule({
    bootstrap: [AppComponent],
    declarations: [
        AppComponent,
        HeaderComponent
    ],
    imports: [BrowserModule, UtilModule, RoutingModule]
})
export class AppModule { }

I just imported ClarityModule and it solved all the problems. Give it a try!

import { ClarityModule } from 'clarity-angular';

Also, include the module in the imports.

imports: [ ClarityModule ],


With components containing Angular Material, a similar error came up with my unit tests. As per @Dan Stirling-Talbert's answer above, added this to my component .spec file and the error was cleared from my unit tests.

Import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'

Then add the schema in the generated beforeEach() statement:

beforeEach(asyn(() => {
    declarations: [ AboutComponent ],
    schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
})
.compileComponents();
}));

My Karma error was: If 'mat-panel-title' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.


Add the following under @NgModule({})in 'app.module.ts' :

import {CUSTOM_ELEMENTS_SCHEMA} from `@angular/core`;

and then

schemas: [
    CUSTOM_ELEMENTS_SCHEMA
]

Your 'app.module.ts' should look like this:

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

@NgModule({
  declarations: [],
  imports: [],
  schemas: [ CUSTOM_ELEMENTS_SCHEMA],
  providers: [],
  bootstrap: [AppComponent]
})

export class AppModule { }