Вы можете сделать это, но вы должны изменить пару вещей в своем подходе.
Директива
app.directive("errorTooltip", function($compile, $interpolate, $timeout) {
return {
scope: true,
link: function($scope, $element, $attrs) {
var errorObj = $attrs.errorTooltip;
var inputName = $attrs.name;
var startSym = $interpolate.startSymbol();
var endSym = $interpolate.endSymbol();
var content = startSym+errorObj+'.'+inputName+endSym;
$element.attr('tooltip-trigger', 'show');
$element.attr('tooltip-placement', 'top');
$element.attr('tooltip', content);
$element.removeAttr('error-tooltip');
$compile($element)($scope);
$scope.$watch(errorObj, function() {
$timeout(function(){
$element.triggerHandler('show');
});
}, true);
$element.on('click', function(e){
$element.triggerHandler('hide');
});
}
};
});
Супер длинное подробное объяснение:
Итак, сверху: @Travis прав в том, что вы не можете просто вводить атрибуты постфактум. Атрибуты всплывающей подсказки, которые вы размещаете в элементе, сами по себе являются директивами, поэтому всплывающую подсказку необходимо скомпилировать, когда она добавлена. Это не проблема, вы можете использовать сервис $compile для этого, но вам нужно сделать это только один раз для элемента.
Кроме того, вам необходимо привязать текст всплывающей подсказки (значение, присвоенное атрибуту всплывающей подсказки) к выражению. Я делаю это, передавая конкатенированное значение $interpolate.startSymbol()
+ значение области видимости, которое вы хотите отобразить (в демонстрации это свойство fieldx объекта ошибок) + $interpolate.endSymbol()
. В основном это оценивается примерно так: {{error.field1}}
. Я использую начальный и конечный символы службы $interpolate, потому что это просто делает директиву более компонентной, поэтому вы можете использовать ее в других проектах, где у вас может быть несколько фреймворков и вы используете что-то кроме двойных фигурных скобок для ваших выражений Angular. Это не обязательно, и вместо этого вы можете сделать: '{{'+errorObj+'.'+inputName+'}}'
. В этом случае вам не нужно добавлять службу $interpolate в качестве зависимости.
Как видите, чтобы сделать директиву действительно пригодной для повторного использования, а не жестко кодировать поле ошибки, я установил значение, данное атрибуту директивы, в имя объекта, за которым будет наблюдаться, и использую входное значение имени в качестве свойства объекта. .
Главное, что вам нужно помнить, это то, что перед компиляцией вы должны удалить атрибут error-tooltip из элемента, потому что, если вы этого не сделаете, вы попадете в бесконечный цикл и сильно упадете. ! По сути, служба компиляции возьмет элемент, к которому прикреплена директива, и скомпилирует его со всеми атрибутами, добавленными вашей директивой. Если вы оставите атрибут error-tooltip, она также попытается перекомпилировать эту директиву.
Наконец, вы можете воспользоваться тем фактом, что всплывающая подсказка не будет отображаться, если ее текстовое значение пусто или не определено (см. строка 192). Это означает, что вам нужно следить только за объектом ошибок, а не за отдельным свойством ошибки, связанной с всплывающей подсказкой. Убедитесь, что вы установили для оператора равенства в $watch
значение true, чтобы он срабатывал при изменении любого из свойств объекта:
$scope.$watch('errors', function() {
$timeout(function(){
$element.triggerHandler('show');
});
}, true); //<--equality operator
В демо вы можете увидеть эффект от изменения объекта ошибок. Если вы нажмете кнопку «Установить ошибки», всплывающая подсказка будет отображаться как для первого, так и для второго ввода. Нажмите «Изменить значения ошибок», и появится всплывающая подсказка для первого и третьего входных данных.
TL;DR:
Добавьте директиву в разметку, задав в качестве значения имя объекта, который будет содержать все ошибки. Обязательно задайте для поля атрибут имени, соответствующий имени ключа свойства в объекте, который будет содержать ошибки для этого ввода, например:
<input class="form-control" ng-model="demo.field1" name="field1" error-tooltip="errors" />
person
jme11
schedule
21.05.2015
attrs.$set('tooltip-trigger', 'show');
не приводят к тому, что обработчик событий всплывающей подсказки прикрепляется к элементу. Angular анализирует html на ранней стадии, но простое изменение атрибута не заставит его внезапно заметить и связать событие. Я не уверен в лучшем способе динамического применения события. Вот несколько связанный ответ: stackoverflow.com/questions/20939754/ - person Travis J   schedule 13.05.2015