导入到核心模块中时,BrowserAnimationsModule不起作用 [英] BrowserAnimationsModule does not work when imported in core module

查看:47
本文介绍了导入到核心模块中时,BrowserAnimationsModule不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将更大的应用程序划分为模块(功能模块,核心模块和共享模块).我正在使用Angular Material,因此导入了BrowserAnimationsModule.我将其放置在共享模块"中,并且一切正常,但是当我想延迟加载某些功能模块时出现了问题-然后出现了关于双重导入BrowserModules的错误.我知道BrowserAnimationsModule应该由核心模块导入,但是当我尝试这样做时,出现以下错误:

Uncaught Error: Template parse errors:
Can't bind to 'ngForOf' since it isn't a known property of 'mat-option'.
1. If 'mat-option' is an Angular component and it has 'ngForOf' input, then verify that it is part of this module.
2. If 'mat-option' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("' | translate}}" (change)="change()" [(ngModel)]="actualFilter" name="food">
          <mat-option [ERROR ->]*ngFor="let filterColumn of displayedColumns" [value]="filterColumn">
            {{filterColumn | t"): ng:///ChargesModule/ChargesComponent.html@9:22
Property binding ngForOf not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("COLUMNFILTER' | translate}}" (change)="change()" [(ngModel)]="actualFilter" name="food">
          [ERROR ->]<mat-option *ngFor="let filterColumn of displayedColumns" [value]="filterColumn">
            {{filt"): ng:///ChargesModule/ChargesComponent.html@9:10

下面,我介绍以下模块: app.module.ts:

    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        HomeModule,
        ChargesModule,
        ModeratorPanelModule,
        CoreModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })

    export class AppModule { }

core.module.ts:

 @NgModule({
      imports: [
        HttpModule,
        HttpClientModule,
        AppRoutingModule,
        SharedModule,
        BrowserAnimationsModule
      ],
      declarations: [
        SidenavComponent,
        HeaderComponent,
        ErrorPageComponent,
        PageNotFoundComponent,
        LoginComponent,
        UpdatePanelComponent,
        DialogConfirmCancelComponent,
        ConfirmMessageComponent,
      ],
      exports: [
        HttpModule,
        HttpClientModule,
        SharedModule,
        HeaderComponent,
        SidenavComponent,
        AppRoutingModule,
        BrowserAnimationsModule
      ],
      providers: [
        AuthService, AuthGuard, HttpAuthService, DictionariesService,
        DictionaryItemFactory, CanDeactivateGuard, { provide: MatPaginatorIntl, useClass: CustomPaginator }
      ],
      entryComponents: [DialogConfirmCancelComponent, ConfirmMessageComponent]
    })
    export class CoreModule { }

shared.module.ts:

export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http);
}
@NgModule({
  imports: [
    CommonModule,
    MaterialModule,
    FlexLayoutModule,
    CdkTableModule,
    FormsModule,
    NgbModule.forRoot(),
    TimepickerModule.forRoot(),
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    })
  ],
  exports: [
    NgbModule,
    TimepickerModule,
    TranslateModule,
    CurrenciesComponent,
    MaterialModule,
    FlexLayoutModule,
    CdkTableModule,
    FormsModule,
    DropDownListComponent,
    DictionariesComponent
  ],
  declarations: [
    DictionariesComponent,
    DropDownListComponent
  ],
  providers: []
})
export class SharedModule { }

在MaterialModule中,我已将所有材料模块与CommonModule一起导入.

解决方案

如果遇到类似错误

由于它不是已知属性,因此无法绑定到"ngForOf"

那么您应该知道它之一:

  • 与未声明的@Input;

  • 有关
  • 或者您在@NgModule配置方面遇到一些问题

由于ngForOf是内置指令,让我们分析@NgModule配置的问题.

首先,我们需要确定此错误的来源.很容易从错误消息中看到:

{{filterColumn | t):ng:///ChargesModule/ChargesComponent.html@9:22

很明显,我们在ChargesModuleChargesComponent中遇到错误.我相信ChargesModule声明看起来像:

charges.module.ts

@NgModule({
  imports: [
    SharedModule,
    ...
  ],
  declarations: [
    ChargesComponent,
    ...
  ]
})
export class ChargesModule {}

现在,如果您尚未阅读我以前的回答 Angular 2使用另一个模块中的组件,我强烈建议您这样做.确保您了解如何在另一个模块中使用一个组件/指令/管道.如果这样做,则仅从SharedModule导出CommonModule,如果仍然有疑问,请继续阅读...

这里的主要规则是

由于我们需要在ChargesComponent模板中使用ngForOf伪指令,该伪指令是ChargesModule的一部分,因此该伪指令应该是传递性ChargesModule中的伪指令的一部分.

这些指令如何收集?

               ChargesModule.directives 
                         + 
      exported directives from imported @NgModules
                        ||
         ChargesModule.transitiveModule.directives

乍看之下,我们会在ChargesModule声明数组中声明ngForOf指令,但是ngForOf已经在CommonModule中声明了,并且由于指令只能是一个模块的一部分,所以我们不能这样做. /p>

因此,请继续在导入的@NgModules中查找ngForOf指令.好吧,我们导入了SharedModule,让我们看看它导出了哪些指令:

shared.module.ts

@NgModule({
  ...,
  exports: [
    NgbModule,
    TimepickerModule,
    TranslateModule,
    CurrenciesComponent,
    MaterialModule,
    FlexLayoutModule,
    CdkTableModule,
    FormsModule,
    DropDownListComponent,
    DictionariesComponent
  ]
})
export class SharedModule { }

SharedModule导出所有为

的指令

@NgModules

导出

 NgbModule,
 TimepickerModule,
 TranslateModule,
 MaterialModule,
 FlexLayoutModule,
 CdkTableModule,
 FormsModule

这意味着,如果NgbModule已导出指令,则它们将被添加到SharedModule的导出指令中.

或仅包含在exports数组中的指令

 CurrenciesComponent,
 DropDownListComponent,
 DictionariesComponent

因为我们在这里没有看到CommonModule,所以我们可以假设我们会收到错误Can't bind to 'ngForOf'

要解决此问题,我们必须在导出数组中添加CommonModule,并且所有元素都应按预期工作.

好的问题是

但是,我不明白为什么只有在之后才出现此问题 将BrowserAnimationsModule从Shared移到Core模块.你能 解释吗?

不知道BrowserAnimationsModule的样子很难理解.让我们通过查看浏览器模块:

@NgModule({
  ...
  exports: [CommonModule, ApplicationModule]
})
export class BrowserModule {

很明显,如果我们从SharedModule导出BrowserAnimationsModule模块,我们也会从CommonModule导出指令,因为:

SharedModule.transitiveModule.directives
               /\
               ||
   BrowserAnimationsModule exports 
               /\
               ||
     BrowserModule that exports
               /\
               ||   
          CommonModule

因此,在将BrowserAnimationModule移至CoreModule之后,您的SharedModule不再导出ngForOf指令,这就是您收到错误的原因.

I divided bigger app into modules (feature modules, core module and shared module). I am using Angular Material and therefore I imported BrowserAnimationsModule. I placed it in Shared Module and everything works fine, but the problem is arising when I want to lazy load some feature modules - then I have error about double import of BrowserModules. I know that BrowserAnimationsModule should be imported by Core Module, but when I am trying to do that, I get following error:

Uncaught Error: Template parse errors:
Can't bind to 'ngForOf' since it isn't a known property of 'mat-option'.
1. If 'mat-option' is an Angular component and it has 'ngForOf' input, then verify that it is part of this module.
2. If 'mat-option' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("' | translate}}" (change)="change()" [(ngModel)]="actualFilter" name="food">
          <mat-option [ERROR ->]*ngFor="let filterColumn of displayedColumns" [value]="filterColumn">
            {{filterColumn | t"): ng:///ChargesModule/ChargesComponent.html@9:22
Property binding ngForOf not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("COLUMNFILTER' | translate}}" (change)="change()" [(ngModel)]="actualFilter" name="food">
          [ERROR ->]<mat-option *ngFor="let filterColumn of displayedColumns" [value]="filterColumn">
            {{filt"): ng:///ChargesModule/ChargesComponent.html@9:10

Below I am presenting the modules: app.module.ts:

    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        HomeModule,
        ChargesModule,
        ModeratorPanelModule,
        CoreModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })

    export class AppModule { }

core.module.ts:

 @NgModule({
      imports: [
        HttpModule,
        HttpClientModule,
        AppRoutingModule,
        SharedModule,
        BrowserAnimationsModule
      ],
      declarations: [
        SidenavComponent,
        HeaderComponent,
        ErrorPageComponent,
        PageNotFoundComponent,
        LoginComponent,
        UpdatePanelComponent,
        DialogConfirmCancelComponent,
        ConfirmMessageComponent,
      ],
      exports: [
        HttpModule,
        HttpClientModule,
        SharedModule,
        HeaderComponent,
        SidenavComponent,
        AppRoutingModule,
        BrowserAnimationsModule
      ],
      providers: [
        AuthService, AuthGuard, HttpAuthService, DictionariesService,
        DictionaryItemFactory, CanDeactivateGuard, { provide: MatPaginatorIntl, useClass: CustomPaginator }
      ],
      entryComponents: [DialogConfirmCancelComponent, ConfirmMessageComponent]
    })
    export class CoreModule { }

shared.module.ts:

export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http);
}
@NgModule({
  imports: [
    CommonModule,
    MaterialModule,
    FlexLayoutModule,
    CdkTableModule,
    FormsModule,
    NgbModule.forRoot(),
    TimepickerModule.forRoot(),
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    })
  ],
  exports: [
    NgbModule,
    TimepickerModule,
    TranslateModule,
    CurrenciesComponent,
    MaterialModule,
    FlexLayoutModule,
    CdkTableModule,
    FormsModule,
    DropDownListComponent,
    DictionariesComponent
  ],
  declarations: [
    DictionariesComponent,
    DropDownListComponent
  ],
  providers: []
})
export class SharedModule { }

In MaterialModule, I have imported all material modules together with CommonModule.

解决方案

If you came across an error like

Can't bind to 'ngForOf' since it isn't a known property

then you should be aware that it either:

  • has to do with undeclared @Input;

  • or you have some problem with @NgModule configuration

Since ngForOf is a built-in directive let's analyze what's the problem with your @NgModule configuration.

First of all we need to determine where this error comes from. It's easy to see from the error message:

{{filterColumn | t"): ng:///ChargesModule/ChargesComponent.html@9:22

It should be clear that we're getting error for ChargesComponent that is part of ChargesModule. I believe ChargesModule declaration looks like:

charges.module.ts

@NgModule({
  imports: [
    SharedModule,
    ...
  ],
  declarations: [
    ChargesComponent,
    ...
  ]
})
export class ChargesModule {}

Now if you haven't read my previous answer Angular 2 Use component from another module i strongly suggest you to do it. Make sure you understand how one component/directive/pipe can be used in other module. If you do then just export CommonModule from SharedModule, if you are still in doubt then read on...

The main rule here is

Since we need to use ngForOf directive within ChargesComponent template, that is part of ChargesModule, then this directive should be part of directives in transitive ChargesModule.

How those directives are collected?

               ChargesModule.directives 
                         + 
      exported directives from imported @NgModules
                        ||
         ChargesModule.transitiveModule.directives

At first glance we would declare ngForOf directive in ChargesModule declarations array but ngForOf is already declared in CommonModule and as directive has to be a part of only one module we can't do that.

Therefore continue looking ngForOf directives among imported @NgModules. Well, we imported SharedModule Let's see which directives it exports:

shared.module.ts

@NgModule({
  ...,
  exports: [
    NgbModule,
    TimepickerModule,
    TranslateModule,
    CurrenciesComponent,
    MaterialModule,
    FlexLayoutModule,
    CdkTableModule,
    FormsModule,
    DropDownListComponent,
    DictionariesComponent
  ]
})
export class SharedModule { }

SharedModule exports all directives that are either

exported from @NgModules

 NgbModule,
 TimepickerModule,
 TranslateModule,
 MaterialModule,
 FlexLayoutModule,
 CdkTableModule,
 FormsModule

This means that if NgbModule has exported directives then they will be added to exported directives of SharedModule.

or just directives included in exports array

 CurrenciesComponent,
 DropDownListComponent,
 DictionariesComponent

As we don't see here CommonModule we can assume we will get the error Can't bind to 'ngForOf'

To solve it we have to add CommonModule to exports array and all should work as expected.

The good question is

However, I do not understand why this problem occured only after moving of BrowserAnimationsModule from Shared to Core module. Can you explain that?

It's hard to understand without knowing how BrowserAnimationsModule looks like. Let's achieve enlightenment by looking at source code:

@NgModule({
  exports: [BrowserModule],
  providers: BROWSER_ANIMATIONS_PROVIDERS,
})
export class BrowserAnimationsModule {
}

and look at BrowserModule:

@NgModule({
  ...
  exports: [CommonModule, ApplicationModule]
})
export class BrowserModule {

It’s immediately obvious that if we export BrowserAnimationsModule module from SharedModule we also export directives from CommonModule since:

SharedModule.transitiveModule.directives
               /\
               ||
   BrowserAnimationsModule exports 
               /\
               ||
     BrowserModule that exports
               /\
               ||   
          CommonModule

So after moving BrowserAnimationModule to CoreModule your SharedModule doesn't export ngForOf directive anymore and that's why you're getting the error.

这篇关于导入到核心模块中时,BrowserAnimationsModule不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆