Я делаю круговую диаграмму для своих данных. Я использую Угловая диаграмма (а затем charts.js).
Мои данные выглядят так (контроллер vm):
vm.persons = [
{
name:'smith',
cart: [
{
id: 1,
category: 'food'
},
{
id: 2,
category: 'clothes'
}
]
},
{
name: 'adams',
cart: [
{
id: 3,
category: 'automobile'
},
{
id:1, category: 'food'
}
]
}
]
Таким образом, мой шаблон выглядит так:
<div ng-repeat = "person in vm.persons">
<div class = "person-header">{{person.name}}</div>
<!-- chart goes here -->
<canvas class = "chart chart-pie" chart-data = "person.cart | chart : 'category' : 'data'" chart-labels = "person.cart | chart : 'category' : 'labels'"></canvas>
<div class = "person-data" ng-repeat = "item in person.cart">
<div>{{item.category}}</div>
</div>
</div>
Я решил использовать фильтр для диаграммы, так как думал, что он будет подходящим, СУХИМ и многоразовым:
angular.module('myModule').filter('chartFilter', function() {
return function(input, datum, key) {
const copy = JSON.parse(JSON.stringify([...input.slice()])); // maybe a bit overboard on preventing mutation...
const entries = Object.entries(copy.reduce((o,n) => {o[n[datum]] = (o[n[datum]] || 0) + 1}, {}));
const out = {
labels: entries.map(entry => entry[0]);
data: entries.map(entry => entry[1]);
};
return out[key];
}
});
ЭТО РАБОТАЕТ, и диаграмма появляется с правильными данными. Однако, согласно консоли, он каждый раз выдает infdig error. Согласно документы, это потому, что я возвращаю новый массив, а я верю, потому что это почти другой набор данных. Даже если я избавлюсь от copy (который должен быть полностью отдельным объектом) и использую input напрямую (input.reduce(o,n) и т. д.), Он все равно выдает ошибку.
Я попытался также превратить его в функцию (в контроллере):
vm.chartBy = (input, datum, key) => {
const copy = JSON.parse(JSON.stringify([...input.slice()])); // maybe a bit overboard on preventing mutation...
const entries = Object.entries(copy.reduce((o,n) => {o[n[datum]] = (o[n[datum]] || 0) + 1}, {}));
const out = {
labels: entries.map(entry => entry[0]);
data: entries.map(entry => entry[1]);
};
return out[key];
};
и в шаблоне:
<canvas class = "chart chart-pie" chart-data = "vm.chartBy(person.cart, 'category', 'data')" chart-labels = "vm.chartBy(person.cart, 'category', 'labels')"></canvas>
Однако это также вызывает ошибку infdig.
Кто-нибудь знает, как не получить каждый раз через ошибку infdig? Это то, что я пытаюсь решить.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Как вы указали, вы не можете привязаться к функции, которая создает новый массив, иначе цикл дайджеста никогда не будет удовлетворен тем, что новое значение соответствует старому, потому что ссылка на массив изменяется каждый раз.
Вместо этого привяжите только к данным, а затем реализуйте фильтр в директиве, чтобы отфильтрованные данные никогда не привязывались, а просто отображались в шаблоне директивы.
HTML
<canvas class = "chart chart-pie" chart-data = "person.cart" chart-labels = "person.cart"></canvas>
JavaScript
app.directive('chartData', function(){
return {
template: '{{chartData | chart : "category" : "data"}}',
scope: {
'chartData': '='
}
}
});
app.directive('chartLabels', function(){
return {
template: '{{chartLabels | chart : "category" : "labels"}}',
scope: {
'chartLabels': '='
}
}
});
app.filter('chart', function() {
return function(input, datum, key) {
...
return out[key];
}
});
Я жестко запрограммировал строки данных / ключей в директивах, но вы можете передать их в качестве дополнительных привязок, если это необходимо.