在 Angular 指令中使用 $filter

Posted

技术标签:

【中文标题】在 Angular 指令中使用 $filter【英文标题】:Using $filter in Angular directive 【发布时间】:2016-06-13 02:04:50 【问题描述】:

我已经构建了一个 Angular 指令来显示 D3 可视化。我在我的 y 轴上的 tickFormat 函数中使用 $filter,如下所示:

ySalesAxis = d3.svg.axis()
  .orient('left')
  .ticks(6)
  .scale(ySalesScale)
  .tickFormat(function(d) 
    return $filter('formatSalesValue')(d.value, 'USD');
  );

我看到的问题是,当页面首次加载时,这些刻度标签都没有出现。事实上,如果我 console.log($filter('formatSalesValue')(d.value, 'USD')) 我得到 6 undefined(因为我的 ticks 属性设置为 6)。但是,一旦我采取行动,例如在画笔过滤器中单击,刻度标签就会显示格式正确。

我的formatSalesValue 过滤器调用了一项服务(异步操作),因为有几十种货币循环进出系统,我从数据库中检索了这些货币的详细信息。我确信这就是我的刻度标签未定义的原因。我可以做些什么来确保这些值在页面加载后立即出现?注意:我尝试将我的 tickFormat 函数包装在对 scope.$apply 的调用中,但我收到了 digest already in progress 错误。

【问题讨论】:

可能是在摘要循环之外调用 tickFormat 的问题。 如果是这样,在你的 return 语句之前添加 scope.$apply() - 假设你在一个指令和链接函数中 创建复制问题的演示 见Replacing d3.js with pure SVG + AngularJS。 有什么办法可以把它放进一个codepen或什么的?我刚刚尝试从 .tween() 调用 $filter ,一切似乎都正常。值 d.value 是 formatSalesValue 所期望的格式吗? 【参考方案1】:

Axis 的 tickFormat 方法运行传递的回调并以同步的方式使用它返回的值。这就是您在第一次调用时得到 undefined 的原因,因为您的 $filter 是异步的。

如果此异步调用仅出于性能原因,您应该使其同步并在其他地方寻找改进。 Angular 是否应该注意这么多独立的变化,它可能会被 $digest 循环阻塞。

如果你制作 JSBin,我可能会告诉你更多。

【讨论】:

【参考方案2】:

TL;DR

尝试使用 Angular $timeout 函数。


根据您的问题,问题可能有很多,但我认为这是问题所在:

可能的问题

它认为问题的一部分是你得到的东西发生在事件循环的一个奇怪的地方。

$timeout 是有用的函数,因为它在当前堆栈被清除并且经过 n 毫秒后运行,如果没有给定延迟时间,则 $timeout 只是在堆栈展开时立即运行。这是在单线程中执行异步代码的有用技巧。

使用延迟为 0 的 $timeout 实际上并不意味着回调将在零毫秒后触发。我只是在处理完任务队列后才被执行。什么时候你想更新你的标签。

$timeout 实际上会在准备就绪时触发摘要。

可能的解决方案

$timeout(function() 
  // Update the label with what comes back from the server
, 0, false);

这是一个很好的视频,解释了 javascript 事件循环是如何工作的:What the heck is the event loop anyway?

【讨论】:

以上是关于在 Angular 指令中使用 $filter的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 2 指令中使用 templateUrl

在 Angular 中使用 HTML 标记作为指令

使用 Angular 指令在模板中绘制对象

如何在 Angular 2 / 4 中使用鼠标滚轮事件测试指令

在 Angular 指令中使用基于 jQuery 的自动完成插件

不能在 Angular 6 的子模块中使用 app 模块内声明的指令