如何在d3工具提示的HTML元素中使用AngularJS过滤器?

4

我有一个网页应用程序,结合了Angularjs和d3js。我的一个指令称为dailyView,使用cfg服务中定义的drawtooltip()函数设置工具提示。指令代码类似于以下内容:

app.directive('dailyView', ['cfg', function (cfg) {

  return {
    restrict: 'E',
    link: function(scope, element, attrs) {
      scope.$watch('daily', function(newVal, oldVal) {
        if (!newVal) return;
        cfg.drawDaily(scope.daily[attrs.bus], element, attrs.bus);
        $('#sortable2').sortable({
            start: scope.dragStart,
            update: scope.dragEnd
        });
        cfg.drawTooltip();
      });
    }
  };
}]);

另一方面,drawTooltip()函数的定义如下:
app.factory('cfg', ['$window', '$rootScope', '$cookieStore', function($window, $rootScope, $cookieStore){
 function drawTooltip(){

  var tooltip = d3.select(".tooltip");

  d3.selectAll(".myImage")
    .on("mousemove", function(d){
      tooltip.transition().duration(100)
        .style("opacity", .9);
      tooltip.html('<p>{{"' + d.measure + '"|myLocationFilter}}</p>')
        .style("left", (d3.event.pageX + 20)  + "px")
        .style("top", (d3.event.pageY - 110) + "px");    
    })
    .on("mouseout", function(d) {
      tooltip.transition().duration(200)
        .style("opacity", 0);
    });
}

我的Angular过滤器应将字符串转换为一个根据浏览器语言变化的描述性文本。问题在于我的过滤器没有被识别,当绑定到元素的measure数据是字符串"plug"时,我的提示框只显示以下文本{{"plug"|myLocationFilter}}。
我该如何将我的Angular过滤器注入到d3js HTML元素中?
注意:这个 是一个相似但尚未得到答案的问题。
编辑1:我已经尝试在指令中调用cfg.drawtooltip()之后立即使用$compile()(scope),但angular过滤器不起作用。
编辑2:在测试评论中提供的多个建议后,清楚地发现问题在于使用了d3选择集的html()方法。是否有可能等待$compile()处理完毕,然后使用结果对象的outerHTML值?

为什么不尝试在d3代码内部对文本进行评估,而不是尝试使其插值? - Jeff Hubbard
http://docs.angularjs.org/api/ng.$compile - Adam Pearce
如果您正在使用 angular 将 HTML 添加到 DOM(通过指令),那么这个答案应该会有所帮助:https://dev59.com/XnjZa4cB1Zd3GeqPe4TQ#19663183 请发一些关于添加此 DOM 元素的更多代码。 - musically_ut
你需要从指令代码中调用编译服务,因此需要将 $scope 传递给 drawTooltip - Pieter Herroelen
Pieter,如果我将作用域传递给drawTooltip,那么我将从我的服务中调用$compile而不是我的指令。我尝试过这样做,但它没有起作用。我还尝试过类似于此参考中的$compile(element.contents())(scope),但似乎也不起作用。 - JAC
显示剩余3条评论
1个回答

0

在输出之前,您需要对值进行$compile()编译。

这行代码:

 tooltip.html('<p>{{"' + d.measure + '"|myLocationFilter}}</p>')

应该是这样的:
 var compiledElement = $compile('<p>{{"' + d.measure + '"|myLocationFilter}}</p>')($rootScope);
 tooltip.html(compiledElement);

这应该可以正常工作。 我在这里做了一个小的 演示。你需要注入并使用 $rootScope,因为你在工厂内调用它,而工厂没有自己的作用域。当然还需要 $compile,它会为你完成魔法。

通常情况下,对于工具提示,使用指令也是一个好主意。


谢谢你的回答。我尝试了相同的方法,但在我的项目中没有起作用,但我不知道为什么。你的回答显示了问题所在。你使用了jquery选择器的html()方法。我使用了d3选择器的html()方法。在这种情况下,html()需要一个字符串而不是一个对象。我尝试使用对象的outerHTML字段,但看起来该字段没有及时编译,我只得到一个文本,上面写着:{{'this becomes uppercase' | uppercase}}。有什么建议可以克服这个问题吗? - JAC
此链接包含您修改后的小样例,以供参考:http://jsfiddle.net/juanargote/yTFVa/。 - JAC
最终我使用了 $q 来确保使用“编译”后的 HTML,并且我还需要访问返回对象的 outerHTML 字段,就像这样:compiledElement[0].outerHTML,但 Armin 的答案指出了问题的根源,因此接受了该答案。 - JAC
@JAC你最终有解决这个问题吗?你所拥有的修改后的fiddle几乎就是我正在尝试实现的,但是在D3选择器中{{value}}中的绑定值没有得到计算。 - Chris Casad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接