javascript - AngularJS 在 ng-repeat 之后添加 jQuery dom 事件监听器

标签 javascript jquery angularjs d3.js

我正在将带有图表的基于 D3 的网站迁移到 Angular。每个单独的图表仍将由 D3 绘制,但每个图表都将使用管理图表的 Angular 指令

其中一个图表元素由图表 (SVG) 和充当其图例的 HTML 表格组成。

[ svg (chart) ][ table (legend) ]

D3 绘制图表,我使用 ng-repeat 绘制图例。在这种情况下,图例和图表都需要是交互式的:需要有 DOM 事件监听器。然而,指令的 Controller 在 ng-repeat 绘制图例之前运行(因此 DOM 元素尚不存在)。

查看:

<div ng-transclude></div>
<div class="wrapper">
    <svg></svg>
    <div class="valign">
        <table>
            <tr>
                <th>#</th>
                <th>Name</th>
                <th>BTC</th>
                <th>USD</th>
            </tr>
            <tr ng-repeat="item in items" class="legend item-{{item.title}}" title="{{item.title}}">
                <th>{{$index + 1}}</th>
                <td>{{item.title}}</td>
                <td>{{item.btc | bitcoin}}</td>
                <td>{{item.usd | currency}}</td>
            </tr>
        </table>
    </div>
</div>

指令:

angular
  .module('d3.charts', [])
  .directive('volumeElement', function() {
    return {
      restrict: 'E',
      scope: {
        data: '='
      },
      transclude: true,
      link: function(scope, element, attrs) {

        // todo: this needs to be changed upstream in the volume controller
        scope.mode = '24h';

        // the d3 chart function
        var chart = new window.WZB.VolumeChart(
          element.find('svg')[0],
          scope.data
        );

        var $paths, $legend;

        var render = function() {
          chart.mode = scope.mode;
          chart.render();

          $paths = element.find('.interactive');

          addHovers();
        }

        var addHovers = function() { 
          // PROBLEM: at this point the ng-repeat has not populated the legend yet
          $legend = element.find('.legend')
          $paths.hover(function(e) {
            var $path = $(e.target);
            var title = $path.attr('title');

            var legend = $legend
              .filter(function() {
                var nonActive = $(this).attr('title') !== title;

                if(!nonActive)
                  $(this).removeClass('blur')

                return nonActive;
              })

              $paths
                .not($path)
                .add(legend)
                .addClass('blur');
            }, function() {
              $paths.add($legend)
                .removeClass('blur');
            })
        }

        render();
      },
      templateUrl: '/volume-element.html'
    }
  })

我使用 jQuery 进行更高级的 DOM 操作,我不能只依赖 Angular 的 ng-mouseover 指令,因为我需要 Angular 生成的表和 D3 生成的 SVG 的事件监听器。

如何在 ng-repeat 填充图例后立即执行代码?

<小时/>

黑客解决方案:

// todo: proper fix
// see @link https://stackoverflow.com/questions/24035289/angularjs-add-jquery-dom-eventlisteners-after-ng-repeat
setTimeout(addHovers, 0);

最佳答案

我重构了代码,我没有以 Angular 方式思考。包含新指令,并且 d3 还创建表格,而不是混合 Angular 和 d3 来实现相同的可视化。这样我就不再需要 jQuery 了。

关于javascript - AngularJS 在 ng-repeat 之后添加 jQuery dom 事件监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24035289/

相关文章:

javascript - 如何在 jQuery 中仅定位当前悬停的元素

javascript - 如何更改AngularJS中的输入类型

javascript - Angular - 将父 Controller 注入(inject)多个子指令

javascript - 如何在 ASP MVC 设置中将 AngularJS 中的变量从一个 Controller 传递到下一个 Controller ?

javascript - vue-i18n 如何缩写货币显示?

javascript - ngClick 在我的 Angular 应用程序中不起作用

javascript - 从循环中的文本数组分页 HTML textarea 内容

javascript - 帮助表单上的appendTo() jquery函数

javascript - 在 Perl 中使用 WWW::Scripter 模块时,如何获取尽可能多的调试流量信息?

javascript - 在转换前动态设置 css 转换