Angular 11 动态加载Contact组件时CrispEdge自定义指令未生效求助
问题描述
我有一个名为 CrispEdgeDirective 的自定义属性指令,在从 Intro组件 动态加载的 Contact组件 中无法正常生效,Contact组件的img标签上并未被添加 crisp-edge CSS类。

intro-component.html 代码
<ng-template #contactContainer></ng-template> <ng-container> <div> <button appButton (click)="showContact()">Contact</button> </div> </ng-container>
intro.component.ts 代码
@Component({ selector: 'app-intro', templateUrl: './intro.component.html', styleUrls: ['./intro.component.css'] }) export class IntroComponent implements OnInit, OnDestroy{ @ViewChild("contactContainer", { read: ViewContainerRef }) public contactContainerRef!: ViewContainerRef; showContact(){ let contactComponentFactory = this.componentFactoryResolver .resolveComponentFactory(ContactComponent); let contactComponent = this.contactContainerRef.createComponent(contactComponentFactory).instance; this.contactCloseSub = contactComponent.close.subscribe(() =>{ this.contactContainerRef.clear(); }) } }
contact.component.html 代码
<div> <div class="row"> <img src="assets/30px.png" class="mx-auto d-block" alt="contact_brand" appCrispEdge> </div> </div>
contact.component.ts 代码
import { Component } from "@angular/core"; @Component({ selector: "app-contact", templateUrl: "./contact.component.html", styleUrls: ['./contact.component.css'] }) export class ContactComponent{ }
crisp-edge.directive.ts 代码
import { Directive, ElementRef, OnInit, Renderer2 } from '@angular/core'; @Directive({ selector: '[appCrispEdge]' }) export class CrispEdgeDirective implements OnInit{ constructor(private elementRef: ElementRef, private renderer: Renderer2) { } ngOnInit(): void{ this.renderer.addClass(this.elementRef.nativeElement,'crisp-edges'); } }
shared.module.ts 代码
import { CrispEdgeDirective } from './../directives/crisp-edge.directive'; import { NgModule } from "@angular/core"; @NgModule({ declarations: [ CrispEdgeDirective, ], exports: [ CrispEdgeDirective ] }) export class SharedModule {}
app-home.module.ts 代码
import { SharedModule } from './shared.module'; import { AppHomeRoutingModule } from './app-home-routing.module'; import { NgModule } from '@angular/core'; import { IntroComponent } from '../components/intro/intro.component'; @NgModule({ imports: [ SharedModule ], exports: [], declarations: [ IntroComponent ] }) export class AppHomeModule{ }
解决方案
核心问题原因
动态加载的ContactComponent未被纳入AppHomeModule的声明体系,即使AppHomeModule导入了带指令的SharedModule,编译器也无法识别ContactComponent模板中的appCrispEdge指令,导致指令不生效。
修复步骤
- 将ContactComponent添加到AppHomeModule的
declarations数组中:
// 调整后的app-home.module.ts @NgModule({ imports: [ SharedModule, AppHomeRoutingModule ], declarations: [ IntroComponent, ContactComponent // 新增该行 ] }) export class AppHomeModule{ }
- (Angular 13+版本可选优化)简化动态组件加载写法,无需手动调用ComponentFactoryResolver解析工厂:
// intro.component.ts中showContact方法优化 showContact(){ const componentRef = this.contactContainerRef.createComponent(ContactComponent); this.contactCloseSub = componentRef.instance.close.subscribe(() =>{ this.contactContainerRef.clear(); }) }
额外排查点
- 检查指令添加的类名与CSS样式类名是否一致:当前指令中添加的类名为
crisp-edges(带s后缀),如果你的样式选择器写的是.crisp-edge(无s),也会出现样式不生效的情况,注意统一拼写。 - 不要在多个NgModule的declarations数组中重复声明CrispEdgeDirective,一个指令仅可在一个NgModule中声明,其他使用场景直接导入导出该指令的SharedModule即可。
内容的提问来源于stack exchange,提问作者Aravind P
相关产品推荐
相关产品推荐

