【问题标题】:How to read nested directive?如何阅读嵌套指令?
【发布时间】:2020-02-15 12:09:02
【问题描述】:

我有一个类似这样结构的自定义按钮组件(为了便于阅读,代码的简化版本):

HTML:

<button type="button" class="btn btn-primary">
    <ng-content select="[appButtonIcon]"></ng-content>
    <i *ngIf="iconClass && !customIcon" class="fa {{iconClass}}"></i>
    {{isIconButton ? '' : text}}
</button>

TS:

@ContentChild(ButtonIconDirective, { static: true }) customIcon: ButtonIconDirective;

而且效果很好。请注意,&lt;ng-content select="[appButtonIcon]"&gt;&lt;/ng-content&gt; 行。我创建了一个自定义指令appButtonIcon,因此用户可以添加自定义图标,例如 SVG 内容。这工作正常,我可以做到:

1

<custom-button text="Test" (clicked)="onClick()">
    <svg appButtonIcon ...>
        <path ... />
    </svg>
</custom-button>

2

<custom-button text="Test" (clicked)="onClick()" iconClass="fa-folder">
</custom-button>

而且它们工作正常。当我将此自定义按钮添加为另一个自定义组件(我的自定义日期选择器切换)的一部分时,问题就开始了。当我这样做时,只有选项会起作用。我只能使用常规图标类或始终使用带有 appButtonIcon 指令的自定义图标:

自定义日期选择器切换 HTML

理想(?):

<app-custom-button (click)="open($event)" iconClass="fa-calendar" isIconButton="true">
    <ng-content select="[appButtonIcon]"></ng-content>
</app-custom-button>

但它不起作用,app-custom-button 永远无法读取我使用指令appButtonIcon 在自定义日期选择器切换中添加的内容。

只有设置了自定义图标的版本才有效:

<app-custom-button (click)="open($event)" iconClass="fa-calendar" isIconButton="true">
    <ng-container appButtonIcon>
        <ng-content select="[appButtonIcon]"></ng-content>
    </ng-container>
</app-custom-button>

这种方法的问题在于,由于我必须手动添加 ng-containerappButtonIcon 指令,它总是会被按钮读取(显然),即使没有由自定义日期选择器切换的用户。但是,如果我删除它,则永远不会读取内部内容,并且始终使用 fa-calendar 类。有办法解决吗?

请查看 StackBlitz 以获取“工作”示例:https://stackblitz.com/edit/angular-ymxtmv

【问题讨论】:

    标签: angular


    【解决方案1】:

    这可以使用ngProjectAs 指令来实现。您可以通过执行以下操作转发对custom-button 的引用:

    <app-custom-button (click)="open($event)" iconClass="fa-calendar" isIconButton="true">
        <ng-content ngProjectAs="[appButtonIcon]" select="[appButtonIcon]"></ng-content>
    </app-custom-button>
    

    通过此更改,您将需要稍微修改自定义按钮以解决未提供customIcon 的情况。 ngProjectAs 是一种编译器技巧,告诉 angular 将其解释为 ButtonIconDirective 但它实际上不是一个,因此在运行时类中的引用是未定义的。将自定义按钮模板更新为以下内容:

    <button type="button" class="btn btn-primary">
      <span #ref>
        <ng-content select="[appButtonIcon]"></ng-content>
      </span>
      <i *ngIf="iconClass && ref.childNodes.length === 0" class="fa {{iconClass}}"></i>
      {{isIconButton ? '' : text}}
    </button>
    

    这个参考逻辑来自这个问题:In Angular 2 how to check whether <ng-content> is empty?

    StackBlitz

    【讨论】:

    • 谢谢!对我来说这听起来有点“骇人听闻”,但老实说,我不认为它看起来有什么不同:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    • 2015-10-24
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    • 2016-10-15
    相关资源
    最近更新 更多