CUSTOM_ELEMENTS_SCHEMA添加到NgModule.schemas中仍显示错误。

208

我刚刚从Angular 2 rc4升级到rc6,并遇到了一些问题。

我在控制台上看到以下错误:

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

这是我的页头组件:

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

这是我的标题模块:

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 { }

我创建了一个叫做util module的包装模块,它导入了HeaderModule:

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

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

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

最后由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 { }
根据我的理解,我正在遵循错误消息中的指示,使用SCHEMA来抑制错误。 但它似乎不起作用。我做错了什么?(希望这不是显而易见的问题,我目前看不到。过去6个小时一直在升级到这个版本...)

1
如果您将其添加到“AppModule”,是否仍然需要将其添加到组件中? - Alessandro Resta
1
同样的问题,对我来说只需添加“schemas:[CUSTOM_ELEMENTS_SCHEMA]”就像魔术般奏效。谢谢:) - AIon
3
如果您将您的“修复方法”作为答案添加到此问题中,那对于其他人来说就清楚了,他们可以从您的解决方案中受益的具体方法是什么。:] - Danny Bullis
21个回答

168

这可以通过以下方法解决:

a)向每个组件添加schemas: [ CUSTOM_ELEMENTS_SCHEMA ],或者

b)添加

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

schemas: [
  CUSTOM_ELEMENTS_SCHEMA
],

到您的模块。


10
不要忘记声明,它位于@angular/core中。类似这样的代码应该能适用: import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; - rlasjunies
1
将 schemas: [ CUSTOM_ELEMENTS_SCHEMA ] 添加到每个组件中,问题得以解决!谢谢! - Pedro Ferreira
3
在Angular 9中不存在“schemas”。 - Renil Babu
6
不,没有解决我的问题……也许这是 Angular 11 的问题。 - Ortund
不确定应该放在哪个组件中。我认为你只需要把它放在模块中即可。 - tshad
显示剩余6条评论

139

我只想在这里添加一些内容。

在新的angular 2.0.0正式版发布后(2016年9月14日),如果使用自定义的html标签,则会报告Template parse errors。自定义标签是指您在HTML中使用的不属于这些标签之一的标签。

看起来需要在使用自定义HTML标记的每个组件中添加schemas:[CUSTOM_ELEMENTS_SCHEMA]这一行。

编辑: schemas声明需要在@NgModule装饰器中。下面的示例显示了一个带有自定义组件CustomComponent的自定义模块,该组件允许在该组件的html模板中使用任何html标记。

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 {}

自定义组件.component.ts

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

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

自定义组件.html

在这里,您可以使用任何您想要的HTML标签。

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

10
谢谢 Caleb。我在运行一个简单的测试时遇到了错误。不过我已经找出来了…… 我没有将 CUSTOM_ELEMENTS_SCHEMA 添加到我的单元测试虚拟模块中。当我添加后,它就不再报错了。 - Nicolas De Irisarri
2
有没有一种方法可以定义允许的自定义元素?使用CUSTOM_ELEMENTS_SCHEMA可能会导致难以找到的错误,但我想在我的控件中为ng-content部分使用自定义元素名称,而不会因为这些特定的元素名称而导致错误,并且不需要为它们创建只是ng-content的组件。 - Jason Goemaat
1
@Caleb,你能否提供一个快速的代码示例来说明你所说的“看起来需要在每个使用HTML标记的组件中添加schemas:[CUSTOM_ELEMENTS_SCHEMA]”是什么意思?看起来Component装饰器不接受schemas参数。 - Danny Bullis
2
嘿 @DannyBullis,与其使用 Component 装饰器,你应该在 NgModule 装饰器中找到它。你需要为该组件创建一个模块,然后在那里指定模式。文档链接和示例。 - Caleb
这将影响此模块中声明的每个组件。 - E.E.33
显示剩余7条评论

58

如果您正在测试具有自定义元素的组件,则在运行单元测试时也可能遇到此问题。在这种情况下,需要将custom_elements_schema添加到在该组件的.spec.ts文件开头设置的testingModule中。以下是header.component.spec.ts设置的示例:

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

4
谢谢!我花了太长时间才找到这个。 - eflat

30

请在'app.module.ts'中@NgModule({})下方添加以下内容:

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

然后

schemas: [
    CUSTOM_ELEMENTS_SCHEMA
]

你的'app.module.ts'应该是这样的:

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

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

export class AppModule { }

7
现在你的整个应用程序都允许自定义标签。 - E.E.33

13

太棒了!这对我有用。我想在我的组件HTML上添加XML元素,但是我一直出现错误。非常感谢。 - Celso Soares
在Angular 8中,我正在使用Angular元素嵌套Angular元素的服务(即在Angular元素内部嵌套另一个Angular元素)。添加CUSTOM_ELEMENTS_SCHEMA并没有起到帮助作用,但是使用NO_ERRORS_SCHEMA确实解决了问题,现在所有独立Angular元素的嵌套都可以完美地工作了。 - Yogi
这对我在TestBed上运行测试有效。元素本来是正常的,但测试失败了。添加schemas: [NO_ERRORS_SCHEMA],一切都好了。 - VSO
两个都对我没用。 - Nimasha Madhushani

11

使用包含Angular Material的组件时,我的单元测试出现了类似的错误。根据上面@Dan Stirling-Talbert的答案,在我的组件.spec文件中添加了这个并且错误从我的单元测试中清除了。

Import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'

然后在生成的beforeEach()语句中添加模式:

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

我的Karma错误是: 如果'mat-panel-title'是Web组件,则将'CUSTOM_ELEMENTS_SCHEMA'添加到该组件的'@NgModule.schemas'中以抑制此消息。


11

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

dashboard.module.ts
在我们想要使用<app-logout>的模块中,导入AccountModule import { AccountModule } from 'util.module';

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

仪表盘组件.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() {}
}

我不需要导入和使用CUSTOM_ELEMENTS_SCHEMA
然而,当dashboard.module懒加载时,它无法正常工作。
在懒加载情况下使用CUSTOM_ELEMENTS_SCHEMA,错误被抑制,但组件未添加到dom中。


idem +1没有更多的错误,但是没有DOM更新了,这个解决方法是为了尝试让那些带有'-'选择器的工作正常,是####!!!&&ù*$。 - user1568220
3
非常感谢,一周后我发现在Ionic中使用延迟加载(lazy loading)无法运行。 - Amr.Ayoub
1
@Arun - 您的解决方案是100%准确的,1)需要添加到导出中,2)不需要custom_elements_schema - Ashwin
我遇到了同样的错误,我在需要的每个模块中设置了我的组件,并在声明子句中使用它们。我没有使用CUSTOM_ELEMENTS_SCHEMA,但是也能正常工作。 - Dave
谢谢,伙计... 完美无误。我的Angular版本是11。 - harish kushwaha

5

这是一篇较长的文章,它提供了对该问题更详细的解释。

问题(在我的情况下)出现在您拥有Multi Slot Content Projection时。

另请参见内容投影以获取更多信息。

例如,如果您有一个看起来像这样的组件:

HTML文件:

 <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文件:

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

而且你想像这样使用它:

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


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

然后,您会遇到模板解析错误,提示“is not a known Angular component”,事实上它并不是一个组件,只是您组件中ng-content的引用:
最简单的修复方法是添加


schemas: [
    CUSTOM_ELEMENTS_SCHEMA
],

将其添加到您的 app.module.ts 文件中。
但是有一种简单而干净的方法来解决这个问题 - 不要使用<my-component-header>在插槽中插入html,而是可以像这样使用类名来完成此任务:
html文件:
 <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>

而且你想像这样使用它:

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

因此...不再存在不存在的组件,因此没有问题,没有错误,在app.module.ts中不需要CUSTOM_ELEMENTS_SCHEMA

所以,如果您像我一样不想将CUSTOM_ELEMENTS_SCHEMA添加到模块中-使用此方法使用组件不会生成错误并且更清晰。

有关此问题的更多信息- https://github.com/angular/angular/issues/11251

有关Angular内容投影的更多信息- https://blog.angular-university.io/angular-ng-content/

您还可以查看https://scotch.io/tutorials/angular-2-transclusion-using-ng-content


1
这正是我正在寻找的,感谢分享! - romeouald

5

只需阅读此帖子并根据 Angular 2 文档:

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.

如果有人遇到这个问题,一旦您将 CUSTOM_ELEMENTS_SCHEMA 添加到 NgModule 中,请确保您使用的任何新自定义元素都有一个“破折号”在其名称中,例如或等。


2
名字里有短横线?为什么要强制这样愚蠢的约定? - Meryan
我只在刚开始使用Ionic3中的惰性加载时遇到了这个问题,而且只有在尝试为Web构建时才会出现。您可以请提供您提到的文档链接吗?谢谢。 - Meryan

4

在/app/app.module.ts文件中解决了这个问题

导入你的组件并声明它

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

@NgModule({
  declarations: [
    MyComponent,
  ]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接