【问题标题】:Angular Directive not working with *ngIf. Calling directive from componentAngular 指令不适用于 *ngIf。从组件调用指令
【发布时间】:2018-06-24 07:18:00
【问题描述】:

我有两个 DIV - 一个始终可见,另一个在我单击按钮后显示(它是可切换的):

<div>
  <div>
    <small>ADDRESS</small>
    <p [appQueryHighlight]="query">{{ address}}</p>
  </div>
</div>

<div *ngIf="showDetails">
  <div>
    <small>NAME</small>
    <p [appQueryHighlight]="query">{{ name}}</p>
  </div>
</div>

我的自定义指令在第一个 DIV 上运行良好(它会更改段落内与“输入”中输入的查询匹配的字母颜色),但在第二个 DIV 上不起作用。

以下是查询为“addr”时“测试地址”的外观示例:

测试 address
其中粗体文本是例如红色文本。

但是当我有名字 John,并且查询是“Joh”时,它也应该用按钮显示一次,但它不是。

据我了解,单击并切换第二个 div 后,我需要重新运行指令。另外,可能我必须延迟执行此操作,因此有时间显示。我该怎么做?

【问题讨论】:

  • 你做错了什么。我怀疑它应该工作
  • @ConnorsFan 我更正了 - “查询”
  • 对不起,我被文档标题误导了,它来自角度 1。但实际上您可以使用 [hidden]="!showDetails"
  • 是的 - 已更正。我猜没有更多的错别字了。我认为@Kaddath 是对的。我应该使用 hidden 而不是 *ngIf。但我正在使用动画 - 不透明度和高度从第一个 div 滑动第二个 div。使用 [hidden] 时将不起作用。有什么建议吗?
  • 如果 ngIf 不显示/隐藏元素,而是如果为 false,它根本不会将它们发布到 DOM。因此,该要素不存在且免于对其采取行动。我是不是误会了什么?如果您改用 ngShow/ngHide,这是否有效。

标签: javascript html angular directive


【解决方案1】:

更新

我的指令的问题与 *ngFor 有关 - 两个 DIV 都位于 ngFor 中。只有在基于查询传播新列表之后,我才必须调用指令 ngOnChanges 或 ngOnInit。我不知道如何做到这一点,目前,在 ngFor 完全加载之前加载指令 - 这会导致问题。

这是我之前的回答:

感谢@iHazCode,我终于设法解决了这个问题。

首先,这可能是这里描述的问题的重复:Angular 4 call directive method from component

因为我的指令根据输入查询突出显示段落中的特定字母,每次查询更改时,该指令都应该触发,因此我使用 ngOnChanges 与该指令。

这不适用于 *ngIf,因为当 ngOnChanges 触发时,第二个 div 和段落不可见。

作为一种解决方法,我们可以使用 @ViewChildren 从 out 组件访问指令:

@ViewChildren(QueryHighlightDirective) dirs;

然后调用它的 ngOnChanges 方法,一旦 div 被切换。就我而言,问题与组件中指令的最后一次出现有关:

toggleDetails() {
  ...
  this.dirs.last.ngOnChanges();
}

这正是我一直在寻找的东西,我希望它会对某人有所帮助。

在我的情况下,我还遇到了另一个问题 - 定义的 DIV 在 *ngFor 中,它也是基于查询传播的,所以我必须确保在调用 ngOnChanges 之前传播列表。我还没有找到解决方案。

【讨论】:

    【解决方案2】:

    ngIf 不显示/隐藏元素。 ngIf 确定元素是否存在于 DOM 上。您可以通过查看呈现页面的来源来验证这一点。将代码更改为使用 ngHide/Show。

    【讨论】:

    • 在使用 *ngIf 时我需要一个解决方案。因此,按下切换按钮后,第二个 DIV 会从第一个(不透明度和高度)开始设置动画。现在,我想重新渲染里面的段落,这样指令就可以应用了。
    • 明白了,有道理。有几种方法可以解决这个问题,但只访问模板支持代码中的元素并运行指令可能更简洁。也许在 ngOnChanges 生命周期钩子期间。看看下面的链接,它有一些使用 ElementRef API 的例子:stackoverflow.com/questions/32693061/…
    • 当我可以访问我的元素时,如何重新运行指令?有没有办法做到这一点?
    • 你说你的代码非常复杂,所以我试图避开具体的例子,但答案是肯定的。您有在组件代码中使用管道的经验吗?它的工作原理完全相同。如果没有,我可以尝试查找或生成一个可能有用的简单示例。
    • 也许这就是解决方案? angular.io/api/core/ViewChildren 我可以获得组件中的所有指令,并重新运行 ngOnChanges 方法。但据我了解,指令中应该有一个内置方法,允许重新运行它或触发更改检测或其他什么?
    猜你喜欢
    • 1970-01-01
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 2017-02-11
    • 2021-05-15
    相关资源
    最近更新 更多