Триггер D3 перерисовать после окончания ng-repeat
У меня есть интересный вопрос относительно приложений, использующих AngularJS и D3. По сути, у меня есть ng-repeat, который повторяется в зависимости от содержимого массива. В этом массиве находятся объекты, которые содержат URL-адрес REST, к которому они периодически обращаются и получают данные. Как только они получают эти данные, график рисуется с использованием D3 (один график для каждого объекта в массиве).
У меня возникла проблема с динамическим добавлением объекта в этот массив с помощью пользовательского ввода и правильной работой чертежа. Похоже, что код d3 перепрыгивает через пушку и пытается выбрать элементы SVG, которые еще не были отрисованы, так как Angular все еще заканчивает добавлять материал в DOM с помощью ng-repeat.
Я попытался использовать $timeout, а также создал пользовательскую директиву, похожую на эту: ng-repeat finish event.
Это работает хорошо, но, похоже, вызывает событие только при первом запуске ng-repeat, а не когда я добавляю другой объект в массив. Есть какие-нибудь комментарии о том, как лучше всего справиться с этой ситуацией? Если бы я мог вызывать событие на основе $ last каждый раз, когда новый объект добавлялся / удалялся, а затем перебирал массив и вызывал функцию рисования, похоже, это сработало бы.
Ура!
Редактировать: код D3 в настоящее время похож на этот http://bl.ocks.org/mbostock/1346410 который представляет собой простое обновление кольцевой диаграммы с предупреждением о том, что перерисовка инициируется вызовом REST. Однако в будущем могут появиться более сложные графики, и именно поэтому я надеялся использовать D3.
Редактирование 2: я переместил весь свой код D3 в пользовательскую директиву, и после долгих раздумий он, кажется, работает почти так, как должен. Не изолируя область действия, пользовательский элемент имеет ту же область действия, что и ng-repeat, и может получить доступ к объекту и его свойствам, а также к соответствующим элементам DOM (в настоящее время я создаю DIV с идентификатором, уникальным для каждого объекта).).
Проблема теперь возникает при использовании d3.select... когда я пытаюсь выбрать DIV, в котором я хочу разместить чертеж, он не позволяет мне выбирать по идентификатору, так как он возвращает ноль... что очень странно в этом если я выберу все ("div"), он может найти нужный мне div, но не позволит мне выбрать только этот.
Вот JsFiddle, показывающий, что я имею в виду... проверьте консоль и увидите, что первый тест возвращает div "obj1", но второй выбор возвращает null.
Если бы я мог заставить это работать, а затем добавить свой холст SVG и рисовать в этом div, я думаю, что это сработало бы!
Соответствующий выбор:
var test = d3.selectAll("div");
console.log(test);
var chart = d3.select("#obj" +obj.id);
console.log(chart);
HTML, который должен создавать div:
<div ng-repeat="object in myData">
<div id="obj{{object.id}}">
Hi
<bars-chart></bars-chart>
</div>
</div>
1 ответ
Там нет необходимости использовать идентификатор для выбора вообще. Вы можете просто выбрать element[0]
передано в угловую директиву link
функция:
var chart = d3.select(element[0]).append('svg')
Например:
angular.module('myApp', []).
directive('barsChart', function () {
return {
restrict: 'E',
link: function (scope, element, attrs) {
var chart = d3.select(element[0]).append('svg').attr({height: 20, width: 20});
chart.append('rect').attr({height: 10, width: 10});
}
};
});
function Ctrl($scope, $timeout) {
$scope.myData = [ {"id":"1"}, {"id":"2"}];
// just to show that it reacts to changes in the data and will render more SVGs
$timeout(function() {
$scope.myData.push({"id":"3"});
}, 3000);
}
Смотрите JSFiddle здесь: