【问题标题】:custom if directive does not show expected results自定义 if 指令未显示预期结果
【发布时间】:2021-04-02 19:26:42
【问题描述】:

在本教程中

https://www.sitepoint.com/practical-guide-angular-directives/

我正在学习如何创建自定义指令。我按照下面发布的代码中所示的步骤进行操作,但是尽管添加了前面提到的网站中解释的确切代码,但当我运行命令时

ng serve --open

我得到了如下图所示的东西。 请让我知道为什么 myCustomIf 不起作用。我说 myCustomIf 不起作用,因为我在 localhost:4200 上得到的内容如发布的图片中所示

请告诉我如何使 myCustomIf 按照上面发布的链接中的教程中的说明工作

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'ngDirective1';
  name = 'Angular';
  condition = false;    

}

app.myCustomeIfDirective.ts

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({
    selector: '[myCustomIf]'
})
export class MyCustomeIfDirective{
    constructor(private templateRef: TemplateRef<any>,private viewContainer: ViewContainerRef){ }

    @Input()
    setMyCustomIf(condition : boolean) {
        if(condition) {
            this.viewContainer.createEmbeddedView(this.templateRef);
        } else {
            this.viewContainer.clear();
        }
    }
}

app.module

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({
    selector: '[myCustomIf]'
})
export class MyCustomeIfDirective{
    constructor(private templateRef: TemplateRef<any>,private viewContainer: ViewContainerRef){ }

    @Input()
    setMyCustomIf(condition : boolean) {
        if(condition) {
            this.viewContainer.createEmbeddedView(this.templateRef);
        } else {
            this.viewContainer.clear();
        }
    }
}

app.component.html

<h1 my-error>Hello {{name}}</h1>
<h2 *myCustomIf="condition">Hello {{name}}</h2>
<button (click)="condition = !condition">Click</button>

图片

【问题讨论】:

    标签: javascript node.js angular typescript


    【解决方案1】:

    如果你打开控制台,它应该会显示如下:

    NG0303:无法绑定到“myCustomIf”,因为它不是 'h2'

    一个 Angular 结构指令,用简短的语法编写(使用*)并接受一个或多个输入,必须有一个与指令的属性选择器同名的@Input(其他输入遵循另一个规则此处描述What is the exact grammar for Angulars structural directives),例如:

    @Directive({
        selector: '[anyAttr]'
    })
    export class MyCustomeIfDirective{
        @Input()
        anyAttr: any;
    

    @Directive({
        selector: '[anotherAttr]'
    })
    export class MyCustomeIfDirective{
        @Input()
        set anotherAttr(val: any) {}
    

    为什么会这样?

    那是因为*ngIf只是扩展版的快捷方式:

    <ng-template [ngIf]="...">...
    

    *anyAttr => <ng-template [anyAttr]="...">...
    

    现在,让我们看看你的代码:

    @Directive({
        selector: '[myCustomIf]'
    })
    export class MyCustomeIfDirective{
        @Input()
        setMyCustomIf(condition : boolean) {
    

    需要注意的几点:

    • setMyCustomIf 在您的情况下只是一种方法
    • 如果将其转换为 setter set MyCustomIfMyCustomIfmyCustomIf 不匹配,因为 js 区分大小写。

    解决办法是:

    @Input()
    set myCustomIf(condition : boolean) {
    

    Ng-run Example

    【讨论】:

    • “Angular 结构指令必须有一个与指令的属性选择器同名的@Input”在一般意义上并不是真的。
    • 我读了你的答案,但仍然不清楚错误在哪里!!代码仍然不起作用
    • @IngoBürk 你能给我一个不正确的例子吗?输入别名和没有输入的指令是例外
    • @user2121 错误在于角度绑定*myCustomIf="condition" 我添加了我的更改示例
    • @yurzui 例如,我有一个项目,其中存在不同的用户角色(查看者,管理员,...),并且有结构指令 *appViewer*appAdmin 只显示那些角色。这些结构性指令没有任何输入。即使它们确实有输入,选择与选择器相同的名称也只是为了使语法更短——结构指令根本不需要工作。
    【解决方案2】:

    在您的指令 (app.myCustomeIfDirective.ts) 中,您需要将输入的名称与指令的名称相匹配(因为条件是通过该属性传递的):

    @Input("myCustomIf")
    set myCustomIf(condition : boolean) {
        if(condition) {
            this.viewContainer.createEmbeddedView(this.templateRef);
        } else {
            this.viewContainer.clear();
        }
    }
    

    (请注意,您也可以更改函数名称以匹配指令名称)

    stackblitz demo

    【讨论】:

    • 很遗憾没有解决问题
    • @user2121 - 查看我的编辑 - 从函数更改为设置器
    • AFAIK,如果你使用相同的输入名称,这里不需要输入别名
    • 你是对的,别名不需要(但不会干扰)
    • 我更改了方法的名称以匹配指令选择器的名称。但仍然没有发生变化..问题仍然存在
    猜你喜欢
    • 1970-01-01
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    • 2019-04-05
    • 2022-08-14
    • 1970-01-01
    • 2015-10-20
    相关资源
    最近更新 更多