3

我有一点疑问ng-init,实际上我有一些图表。

  1. 顶部趋势线
  2. 下面的饼图。
  3. 下面的 HTML 表。

在页面加载时我没有显示任何内容,但是一旦我第一次单击特定按钮,我的整个图表和表格就会显示为 http 请求接收到的数据。但之后,如果我单击另一个按钮并执行相同的 http 请求,则它会更新趋势线和表格,但不会更新饼图。我的饼图使用 ng-init 在下面的 div 中呈现,当我测试 ng-init="myFunction(index)" 方法时,它不会在随后的点击中更新。

<form>
  <md-input-container>
    <label for="myInput">Search Division</label>
    <md-icon md-svg-icon="~/Content/myIcons/searchicon/ic_search_black_36px.svg"></md-icon>
    <input type="text" id="myInput" ng-model="searchDiv" md-autofocus>
  </md-input-container>
  <md-content ng-repeat="prod in listofProd | filter: searchDiv">
    <md-button class="md-whiteframe-1dp card" ng-click="generateChart(prod)" flex-sm="100" flex-gt-sm="100" flex-gt-md="100">
    {{prod}}
    </md-button>
  </md-content>
</form>

<div layout="row" layout-wrap>
  <div flex="25" style="width:1000px;height:300px; border: 1px solid skyblue;" ng-repeat="year in years track by $index" id="piechart{{$index}}" ng-init="myFunction($index)">
  </div>
</div>

这是我的 ng-init 函数的 angularjs 代码。

(function () {
  'use strict'
  angular.module("GAiiNSApp").controller("ProdPerDash", ['$http', '$scope', '$log', function ($http, $scope, $log) {
    $scope.isLoading = false;
    $scope.hideme = true;
    var currentdate = new Date();
    var startdd = "01";
    var startmonth = "00";
    var lastyear = currentdate.getFullYear() - 3;
    var enddd = "31";
    var endmonth = "11";
    var endyear = currentdate.getFullYear();
    $scope.StartDate = new Date(lastyear, startmonth, startdd);
    $scope.EndDate = new Date(endyear, endmonth, enddd);
    $scope.Region = "Local";
    $scope.Country = "";
    $scope.ProductLineSelected = false;
    $scope.ButtonText = "CUSTOMIZE";

    $scope.clicked = false;
    $scope.Yes = function () {
      if (!$scope.clicked == true) {
        $scope.ButtonText = "CANCEL";
        $scope.clicked = true;
      }
      else {
        $scope.ButtonText = "CUSTOMIZE";
        $scope.clicked = false;
      }
    }
    $scope.alert = function (message) {
      $window.alert(message);
    }

    $scope.Regions = ["Export", "Local"];
    $http.get('/General/API/GetProductDivision').then(function (res) {
      $scope.listofProd = res.data;
    });
    $scope.selectedProduct = "";
    $scope.generateChart = function (prodname) {
      $scope.selectedProduct = prodname;
      $scope.isLoading = true;
      $http.get('/Marketing/MarketingAPI/ProdPerformance', {
        params: {
          StartDate: $scope.StartDate,
          EndDate: $scope.EndDate,
          ProductDivision: prodname,
          Division: $scope.Region,
          Area: $scope.Country
        }
      }).then(function (res) {
        var resArray = res.data;
        var trendarray = [];
        $scope.TableRecords = resArray;
        $scope.hideme = false;
        var json = resArray;
        // console.log("Array of Objects: " + JSON.stringify($scope.TableRecords));
        var groupedData = {};
        var result = [];
        resArray.forEach(function (item) {
          var year = item.SecuredYear;
          var value = item.ValueInDhs;
          if (groupedData.hasOwnProperty(year)) {
            groupedData[year] += value;
          } else {
            groupedData[year] = value;
          }
        });
        //Pie chart data starts here
        var years = [];
        json.forEach(function (obj) {
          if (years.indexOf(obj.SecuredYear) == -1)
            years.push(obj.SecuredYear);
        });
        //$scope.years = years;
        $scope.years = angular.copy(years);
        $scope.pichartsview = true;
        $scope.myFunction = function (index) {

          var data = [['Product', 'ValueInDhs']];
          json.forEach(function (obj) {
            if (obj.SecuredYear == years[index]) {
              data.push([String(obj.GroupName).trim(), obj.ValueInDhs]);
            }
          });
          $scope.displayChart(data, index);
        }
        $scope.displayChart = function (dataForChart, index) {
          var chartData = dataForChart;
          google.charts.load('current', { 'packages': ['corechart'] });
          google.charts.setOnLoadCallback(drawChartPie);
          function drawChartPie() {
            var data = google.visualization.arrayToDataTable(chartData);
            var options = {
              chartArea: { left: 10, top: 20, width: "80%", height: "80%" },
              legend: 'bottom',
              is3D: true,
              pieSliceText: 'percentage',
              pieSliceTextStyle: {
                fontSize: 8
              },
              title: $scope.selectedProduct + " - " + $scope.years[index]
            };
            var chart = new google.visualization.PieChart(document.getElementById('piechart' + index));
            $scope.$apply(function () {
              chart.draw(data, options);
            });
          }
        }
        //Pie chart data ends here
        for (var year in groupedData) {
          var tmp = {};
          tmp[year] = groupedData[year];
          result.push(tmp);
        }
        result.forEach(function (obj, index) {
          var key = Object.keys(obj)[0];
          trendarray.push([parseInt(key, 10), obj[key]]);
        });
        trendarray.splice(0, 0, [{ label: 'SecuredYear', type: 'number' }, { label: 'ValueInDhs', type: 'number' }]);
        google.charts.load('current', { 'packages': ['corechart'] });
        google.charts.setOnLoadCallback(drawChart);
        $scope.isLoading = false;
          function drawChart() {
            var data = google.visualization.arrayToDataTable(
              trendarray
              );
            var options = {
              legend: 'none',
              title: 'Product Performance Trendline - ' + $scope.selectedProduct + " - " + $scope.Region,
              hAxis: { title: 'Secured Year', format: '0' },
              vAxis: { title: 'Secured Value in DHS' },
              trendlines: {
                0: {
                  lineWidth: 5,
                  type: 'polynomial',
                  visibleInLegend: true,
                  color: 'green',
                }
              }
            };
            var chart = new google.visualization.ScatterChart(document.getElementById('chart_div2'));
            chart.draw(data, options);
          }
        })
    $scope.ProductLineSelected = true;
    };
  }]); //this is ctrl closing
})(); //this is function closing
4

2 回答 2

1

由于Angular 1.2,它有一个选项track by可以防止转发器重新渲染所有项目以提高性能。

更多信息请访问: http: //www.codelord.net/2014/04/15/improving-ng-repeat-performance-with-track-by/

这就是为什么自从您使用了here之后ng-init,就不再为相同的渲染再次触发了。yearstrack byng-repeat="year in years track by $index"

即使您删除它,ng-init也不会再次触发第二次,因为years这里的数组Angular足够出色,可以通过其值进行跟踪,尽管没有明确track by的 .

因此,我们必须将years简单数组更改为object array喜欢,以让 Angular在每次对象更改时[{year: obj.SecuredYear}]生成一个不相同的数组,并且 Angular 将通过触发重绘转发器。$$hashKeyng-init

所以与此相关的变化是,

html

<div flex="25" style="width:1000px;height:300px; border: 1px solid skyblue;" 
  ng-repeat="year in years" id="piechart{{$index}}" ng-init="myFunction($index)">
</div>

JS(填充years

    var years = [];
    json.forEach(function (obj) {
      var exists = years.filter(function(y) {
        return y.year === obj.SecuredYear;
      });

      if (exists.length === 0) { // This will replace the `indexOf` check
        years.push({year: obj.SecuredYear});  // change here
      }
    });
    $scope.years = years;

JS(我的函数())

      $scope.myFunction = function (index) {
      var data = [['Product', 'ValueInDhs']];
      json.forEach(function (obj) {
        if (obj.SecuredYear == years[index].year) {   // change here at years[index].year
          data.push([String(obj.GroupName).trim(), obj.ValueInDhs]);
        }
      });
      $scope.displayChart(data, index);
    };

我刚刚创建了一个示例片段,如下所示,每次单击按钮时,都会使用其中成功记录的console.log(years[index].year);内部进行检查。$scope.myFunction()ng-initGenerate Chart

angular.module('myApp', []);

function MyCtrl($scope) {
    var json = [{SecuredYear: 1965},{SecuredYear: 1988}, {SecuredYear: 2016}, {SecuredYear: 2012}];
    $scope.generateChart = function(item) {
      
        var years = [];
        json.forEach(function (obj) {
          var exists = years.filter(function(y) {
            return y.year === obj.SecuredYear;
          });
          
          if (exists.length === 0) {
            years.push({year: obj.SecuredYear});
          }
        });
        $scope.years = years;
      
        
        $scope.myFunction = function (index) {
          var data = [['Product', 'ValueInDhs']];
          json.forEach(function (obj) {
            if (obj.SecuredYear == years[index].year) {
              //data.push([String(obj.GroupName).trim(), obj.ValueInDhs]);
              console.log(years[index].year);
            }
          });
          //$scope.displayChart(data, index);
        };
    };
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
    <div ng-controller="MyCtrl">
        <button ng-click="generateChart()">Generate Chart</button><br/>
        <div style="border: 1px solid skyblue;" ng-repeat="year in years" id="piechart{{$index}}" ng-init="myFunction($index)" >{{year.year}}
        </div>
    </div>
</div>

于 2016-12-10T14:55:47.970 回答
0

angular.module('app', [
    'googlechart'
  ])
  .controller('appCtrl', function() {
    let vm = this;
    vm.charts = [];

    vm.addChart = function() {
      vm.charts.push({
        type: "PieChart",
        data: {
          "cols": [{
            id: "t",
            label: "Topping",
            type: "string"
          }, {
            id: "s",
            label: "Slices",
            type: "number"
          }],
          "rows": [{
            c: [{
              v: "Mushrooms"
            }, {
              v: 3
            }, ]
          }, {
            c: [{
              v: vm.input.name
            }, {
              v: vm.input.quantity
            }]
          }, {
            c: [{
              v: "Olives"
            }, {
              v: 31
            }]
          }, {
            c: [{
              v: "Zucchini"
            }, {
              v: 1
            }, ]
          }, {
            c: [{
              v: "Pepperoni"
            }, {
              v: 2
            }, ]
          }]
        }
      });
    };
    return vm;
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-google-chart/0.1.0/ng-google-chart.min.js" type="text/javascript"></script>
<div ng-app="app" ng-controller="appCtrl as vm">
  <div ng-repeat="chart in vm.charts track by $index">
    <div google-chart chart="chart" style="height:150px; width:100%;"></div>
  </div>
  <br>
  <input type="text" required ng-model="vm.input.name" placeholder="Enter name">
  <input type="number" required ng-model="vm.input.quantity" placeholder="Enter quantity">
  <button ng-click="vm.addChart()">Add chart</button>
</div>

我注意到您正在使用谷歌图表。您的问题源于使用不兼容的库(谷歌图表不知道模型的变化 - 在这种情况下是角度的)。

可以编写自己的指令,但如果其他人已经完成了繁重的工作,为什么还要这样做呢?相反,我建议您考虑使用以下指令

这是一个活生生的例子。

编辑:ng-init不能按您希望的方式工作只是在控制器ng-init加载时触发一个函数,而不是在渲染元素时。

于 2017-01-15T16:08:39.753 回答