Angular独立组件导入独立指令报NG8002错误的解决方法
问题:Angular独立组件中指令绑定报错NG8002
报错信息:
✘ [ERROR] NG8002: Can't bind to 'appMenuChildPosition' since it isn't a known property of 'ul'. [plugin angular-compiler]
我尝试创建一个指令,用于获取父元素坐标并利用父元素的x、y坐标修改子元素位置。组件和指令均为独立类型,且已将指令导入组件,但仍出现上述报错。
组件代码
@Component({ selector: 'app-home', standalone: true, imports: [NgIf, NgFor, TruncatePipe, LocaleConverterPipe, MenuChildPositionDirective], templateUrl: './home.component.html', styleUrls: ['./home.component.sass'], animations: [fadeOut] }) export class HomeComponent implements OnInit, OnDestroy { public isLoading: boolean = true; public settings?: Settings; public error?: HttpErrorResponse; private isDestroyed$ = new Subject<void>(); constructor( private backendService: BackendService, private utilsService: UtilsService ) {} public ngOnInit(): void { this.backendService.get_settings() .pipe( takeUntil(this.isDestroyed$) ) .subscribe({ next: (data: Settings) => this.settings = data, error: (error: HttpErrorResponse) => this.error = error, complete: () => this.setup(this.settings) }); } public ngOnDestroy(): void { this.isDestroyed$.next(); this.isDestroyed$.complete(); } public open(event: MouseEvent, element: NavigationElement): void { const parentElement = event.target as HTMLElement; const rect = parentElement.getBoundingClientRect(); element.coords = {x: rect.left, y: rect.top}; element.opened ? element.opened = false : element.opened = true; } private setup(settings?: Settings): void { this.isLoading = false; if (!settings) return; if (settings.account.bid) this.utilsService.saveItem('bid', settings.account.bid); } }
指令代码
@Directive({ selector: '[appMenuChildPosition]', standalone: true }) export class MenuChildPositionDirective implements OnChanges { @Input() parentX?: number; @Input() parentY?: number; constructor(private element: ElementRef) {} ngOnChanges(changes: SimpleChanges): void { if (changes['parentX'] || changes['parentY']) { this.adjustPosition(); } } private adjustPosition(): void { console.log(this.parentX, this.parentY); } }
模板代码
<nav> <ul class="menu"> <li *ngFor="let item of settings?.nav"> <p class="link" *ngIf="item.children" (click)="open($event, item)">{{ item.name[0] }}</p> <a *ngIf="!item.children" [href]="item.name[1]">{{ item.name[0] }}</a> <ng-container *ngIf="item.children"> <ul [class.hide]="!item.opened" class="popup-menu" [appMenuChildPosition] [parentX]="item.coords?.x" [parentY]="item.coords?.y"> <li *ngFor="let sub of item.children"> <a [href]="sub.name[1]">{{ sub.name[0] }}</a> </li> </ul> </ng-container> </li> </ul> </nav>
解决方案
报错的核心原因是模板中指令的绑定方式错误:你用了[appMenuChildPosition](方括号绑定),但这个指令的selector是属性选择器,且指令本身没有定义名为appMenuChildPosition的@Input()属性,Angular会将其视为要绑定的属性,从而报错。
修改步骤:
将模板中的[appMenuChildPosition]改为appMenuChildPosition(去掉方括号),作为属性指令直接应用到元素上即可:
<ul [class.hide]="!item.opened" class="popup-menu" appMenuChildPosition [parentX]="item.coords?.x" [parentY]="item.coords?.y">
补充说明:
如果你的指令需要一个与指令同名的主输入属性(比如要通过[appMenuChildPosition]="someValue"传递数据),可以在指令中添加:
@Input() appMenuChildPosition?: any;
但当前你的指令不需要这个主输入,仅需应用指令并传递parentX/parentY两个输入属性,所以直接去掉方括号即可解决问题。
内容的提问来源于stack exchange,提问作者s_spirit
相关产品推荐
相关产品推荐

