Как директива может ожидать обработки динамически интерполированных атрибутов элемента?

72
10

У меня есть директива, называемая "соединение", которая рисует соединительную линию между двумя другими div, заданными идентификаторами div. Иды передаются косвенно через некоторые данные области.

Моя директива "connection" должна получить ограничивающий прямоугольник названных элементов DOM, чтобы она могла нарисовать соединительную линию между ними с соответствующими координатами.

Однако в моей функции ссылки ссылка, вызывающая getElementById() для этих идентификаторов возвращает undefined. Это связано с тем, что в DOM идентификаторы этих элементов по-прежнему находятся в форме id="intf-{{intf.id}} ", когда выполняется моя функция ссылки на соединение (т. id="intf-{{intf.id}} Они еще не были интерполированы).

Разделы, о которых идет речь, были сгенерированы с помощью ng-repeat и были назначены их идентификаторы динамически.

Основной вопрос

Как я могу заставить свою директиву дожидаться, пока идентификаторы элементов пройдут интерполяцию, а затем немедленно уведомит мою директиву, чтобы она могла обновить данные своего шаблона и/или области видимости?

В качестве альтернативы, я могу заставить интерполяцию произойти немедленно, чтобы getElementById() работал, а затем продолжал мою функцию ссылки?

$ Наблюдать?

Я видел, что вы можете использовать attrs.$observe() знать, когда ваш собственный attr обновился, но я не вижу, как это сделать с произвольным элементом attrs. На самом деле, я даже не могу получить элемент до тех пор, пока его имя не будет интерполировано, так как это единственный способ определить его.

Неполное решение

В качестве неполного решения предыдущий разработчик, который работал над этим кодом, добавил что-то вроде этого:

link: function( scope, element, attrs ) {
var deferUntilElementsExist = function( newVal, oldVal, cb ){
var sourceElement = document.getElementById(scope.connection.source().id);
var targetElement = document.getElementById(scope.connection.target().id);
if( !sourceElement || !targetElement ) {
$timeout( function(){ deferUntilElementsExist( newVal, oldVal, cb ); }, 0 );
return;
}

updatePath();
if (cb) {
cb( newVal, oldVal );
}
};

Такие работы, но линии появляются очень медленно, например, 5 в секунду или даже когда их сотни, как будто они обрабатывают одну строку за цикл обновления или что-то в этом роде.

Благодарю.

спросил(а) 2014-07-30T01:43:00+04:00 6 лет, 2 месяца назад
1
Решение
57

Комментарий от @pixelbits привел меня в правильном направлении. Добавление третьего параметра в значение $ timeout() установлено в false, что предотвращает $ apply() после каждого вызова, что делает "Неполное решение" работать намного быстрее.

link: function( scope, element, attrs ) {
var deferUntilElementsExist = function( newVal, oldVal, cb ){
var sourceElement = document.getElementById(scope.connection.source().id);
var targetElement = document.getElementById(scope.connection.target().id);
if( !sourceElement || !targetElement ) {
$timeout( function(){ deferUntilElementsExist( newVal, oldVal, cb ); },
0, false ); // Added third parameter here set to false
return;
}

updatePath();
if (cb) {
cb( newVal, oldVal );
}
};

ответил(а) 2014-07-30T23:41:00+04:00 6 лет, 2 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема