CUSTOM_ELEMENTS_SCHEMA added to NgModule.schemas s

2020-01-24 10:54发布

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...)

14条回答
甜甜的少女心
2楼-- · 2020-01-24 11:36

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();
  }));
查看更多
叛逆
3楼-- · 2020-01-24 11:36

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

angular2-template-loader

and put it

test: /\.ts$/,
   loaders: ['awesome-typescript-loader', 'angular2-template-loader']
查看更多
Root(大扎)
4楼-- · 2020-01-24 11:39

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.

查看更多
smile是对你的礼貌
5楼-- · 2020-01-24 11:42

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.

查看更多
Lonely孤独者°
6楼-- · 2020-01-24 11:45

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

查看更多
forever°为你锁心
7楼-- · 2020-01-24 11:46

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 ]
        });

    });
查看更多
登录 后发表回答