带有ng-init的AngularJS元素指令在视图渲染之前运行

时间:2014-03-22 23:37:48

标签: javascript angularjs angularjs-directive angularjs-ng-repeat

我试图遍历一个数组并创建一个自定义指令的多个实例,这些实例根据rootScope上的一些变量创建不同的图形。一切正常,除非我尝试将它们放在视图中并将ng-init调用到范围上的方法并传递参数。

我发现ng-init似乎在任何事情之前运行(并且我认为ng-init是错误的方法),这会导致错误,因为在方法中设置的变量尚未设置ng-init在视图中运行。

当我第一次加载索引视图时,然后进入此视图,一切都很好,但是当我尝试首先加载此视图或重新加载它时,我收到了错误。 ng-init试图在其他任何运行之前调用chart()方法。

在索引视图中,我将这个图表放在一个名为onclick的模态中,因此不需要ng-init,因此它工作得很好。

我有点陷入困境,我需要的是关于"权利"或更好的方法来实现这一目标。

在详细视图中,我需要遍历该数组以获得基于四个不同数据对象的四个图表。

现在数据是一个静态文件,因为这是一个原型。

我的代码基本上是这样的: 查看:

<div id="chart_list">
  <div class="chart" ng-repeat="val in ['abc', 'def', 'ghi', 'jkl']" ng-init="chart('line', val, itemId, val)">
    <h3>{{val | uppercase}}</h3>
    <chart/>
  </div>
</div>

AppController方法:

// get data set up for chart consumption
$scope.chart = function(chart, kpi, socId, chartId) {

$rootScope.visualize = {};
$rootScope.visualize.chart = chart;
$rootScope.visualize.chartId = chartId;
$rootScope.visualize.val = val;
$rootScope.visualize.item = $rootScope.itemList[itemId];
$rootScope.visualize.valName = $rootScope.visualize.item[val].name;

};

DetailView控制器:

app.controller('ItemDetailController', function($scope, $rootScope, $routeParams, ItemList) {

  var itemId = $scope.itemId = $routeParams.itemId;

  ItemList.get({}, function(res) {
    $rootScope.itemList = res.data;
    $scope.item = $rootScope.itemList[itemId];
  });


});

服务:

app.factory('ItemList', function($resource){
  return $resource("/api/item-list.json");
});

指令:

app.directive('chart', function() {
  return {
    restrict: 'E',
    link: function(scope, element, attrs){

      if ($(window).width() <= 1200){
        var width = 300;
      } else {
        var width = 450;
      }

      var visualize = scope.visualize;
      var data = visualize.soc[visualize.val].data;
      var numTicks = Object.keys(data).length;

      element.append('<div class="chart_container"><div id="y_axis' + visualize.chartId +'" class="y_axis"></div><div id="chart' + visualize.chartId + '" class="chart"></div><div id="x_axis' + visualize.chartId + '" class="x_axis"></div></div>');
      element.append('<div id="legend_container' + visualize.chartId +'" class="legend_container"><div id="smoother' + visualize.chartId +'" title="Smoothing"></div><div id="legend' + visualize.chartId +'"></div></div>');

      var valSeries = [];
      var valSeries2 = [];
      var valSeries3 = [];
      var valMap = {};
      var i = 0;

      Object.keys(data).forEach(function(propertyName) {
        var value = data[propertyName];
        var val2 = (Math.random() * (102 - 87) + 86) / 100;
        var val3 = (Math.random() * (95 - 70) + 69) / 100;
        valSeries.push({x: i, y: data[propertyName].amount});
        valSeries2.push({x: i, y: data[propertyName].amount * val2});
        valSeries3.push({x: i, y: data[propertyName].amount * val3});
        valMap[i] = data[propertyName].name;
        i++;
      });

      var graph = new Rickshaw.Graph({
        element: document.querySelector('#chart' + visualize.chartId), 
        width: width, 
        height: 150,
        renderer: visualize.chart,
        stroke: true,
        series: [
          {
            data: valSeries3,
            color: '#F0AD4E',
            name: 'Three years ago',
          },
          {
            data: valSeries2,
            color: '#5BC0DE',
            name: 'Two years ago',
          },
          {
            data: valSeries,
            color: '#5CB85C',
            name: 'Past year'
          }
        ]
      });

      var format = function(n) {
        var map = valMap;
        return map[n];
      }

      var x_ticks = new Rickshaw.Graph.Axis.X({
        graph: graph,
        width: width,
        orientation: 'bottom',
        element: document.getElementById('x_axis' + visualize.chartId),
        pixelsPerTick: width/numTicks,
        tickFormat: format
      });

      var y_axis = new Rickshaw.Graph.Axis.Y({
        graph: graph,
        orientation: 'left',
        tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
        element: document.getElementById('y_axis' + visualize.chartId),
      });

      graph.render();

      var hoverDetail = new Rickshaw.Graph.HoverDetail({
        graph: graph,
        formatter: function(series, x, y) {
          var content = app.lib[visualize.dataFormat](parseInt(y)) + "<br>";
          return content;
        }
      });

      var legend = new Rickshaw.Graph.Legend( {
        graph: graph,
        element: document.getElementById('legend' + visualize.chartId)

      } );

      var shelving = new Rickshaw.Graph.Behavior.Series.Toggle( {
        graph: graph,
        legend: legend
      } );

    }
  };
});

修改
我通过完全删除图表方法并用属性替换ng-init来解决这个问题。像这样:

<chart data-attrone="somedata" data-attrtwo="some other data" />

然后在指令中可以使用attrs.attrone等来获取attrs。

属性名称必须小写。

希望这可以帮助将来的某个人。

1 个答案:

答案 0 :(得分:1)

我通过完全删除图表方法并用属性替换ng-init来解决这个问题。像这样:

<chart data-attrone="somedata" data-attrtwo="some other data" />

然后,使用attrs.attrone等指令中的attrs可用。

属性名称必须小写。

希望这有助于将来。