我对ng-init
有点疑惑,其实我有一些图表。
- 顶部的趋势线
- 下方的饼图。
- 下面的 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
最佳答案
Since
Angular 1.2
, it has an optiontrack by
to prevent the repeater from re-rendering all the items to improve the performance.
更多信息请访问:http://www.codelord.net/2014/04/15/improving-ng-repeat-performance-with-track-by/
这就是为什么 ng-init
不会在相同的 years
中再次触发,因为您在这里使用了 track by
ng-repeat="按 $index 跟踪的年份"
。
即使你删除它,ng-init
也不会第二次触发,因为 years
这里是 Angular
所在的数组尽管没有明确的 track by
,但足以根据其值(value)进行跟踪。
因此,我们必须将 years
从简单数组更改为 object 数组
,例如 [{year: obj.SecuredYear}]
到让 Angular 生成一个 $$hashKey
,当对象每次更改时它都不相同,Angular 将通过触发 ng-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(填充年
)
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);
};
我刚刚创建了一个示例片段,如下所示,以使用 $scope 中的
每次点击 console.log(years[index].year);
进行检查。 myFunction()Generate Chart
按钮时,它都会使用 ng-init
成功记录。
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>
关于javascript - AngularJS ng-repeat 不重新渲染转发器(UI)并且不再次调用 ng-init,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41038466/