Лучший способ обернуть исходный элемент из Директивы?
Я пишу Директиву (используя AngularJS 1.2.0-rc2, если это имеет значение), который добавляет кнопку "clear" (подумайте о кнопке "x", которую браузер добавляет для элементов <input type="search">
), в <input>
.
Поскольку кнопка "clear" вводится из Директивы и абсолютно позиционируется, я хотел бы содержать как существующую <input>
, так и недавно добавленную кнопку "clear" в элементе обертки, который имеет position: relative
, чтобы обеспечить правильное позиционирование кнопки "clear".
Объявленный HTML выглядит следующим образом:
<input type="text" id="myField" data-ng-model="someModel" data-search>
Директива, которую я имею до сих пор:
angular.module('myApp', []).directive('search', function() {
var
clear = angular.element('<a href role="button" class="btn x" style="display:none">×</a>'),
wrapper = angular.element('<div style="position: relative"></div>');
return {
restrict: 'A',
link: function( scope, element, attrs ) {
element.wrap(wrapper.append(clear));
// more code that not relevant to my question
}
};
});
В результате HTML я получаю
<div style="position: relative">
<a href role="button" class="btn x" style="display: none">×</a>
<input type="text" id="myField" data-ng-model="someModel" data-search>
</div>
это то, что мне нужно, но я хотел бы идеально сфокусировать два новых элемента и абстрагировать манипуляции DOM из моей функции link
.
Мне кажется, что есть лучший способ сделать это, используя либо или оба параметра replace
/template
и transclude
, но я не уверен, как сохранить и использовать исходный элемент (со всеми его атрибуты и привязки данных) с любой из этих опций.
Также обратите внимание, что хотя мой образец имеет ng-model
, определенный в исходном элементе, это следует считать необязательным. Я также хотел бы, чтобы директива ограничивалась атрибутами (restrict: 'A'
).
Ответы
Ответ 1
Заключение - это, вероятно, то, что вы ищете. Вот обновленный код.
Шаблон:
<div style="position: relative">
<a href role="button" class="btn x" style="display: none">×</a>
<div ng-transclude></div>
</div>
Директива
angular.module('myApp', []).directive('search', function() {
return {
restrict: 'A',
replace: true,
transclude: true,
// template: '', // string template of the HTML above, or better yet
templateUrl: '', // relative URL of an HTML file containing the above template
};
});
HTML:
<div data-search>
<input type="text" id="myField" data-ng-model="someModel">
</div>
Вы должны использовать только один из шаблонов или templateUrl в директиве, я бы склонялся к templateURL, потому что ненавижу строковые шаблоны.
Вы можете по-прежнему включать функцию ссылок, если вам нужно больше логики.
Свойство replace заменит существующий элемент DOM, к которому вы полностью примените элемент, оставив это свойство, сохранит элемент и поместит ваш шаблон в него. До вас, как вы хотите, чтобы это было настроено.
Размышляя об этом еще, если вы это сделали:
transclude: 'element'
Вы можете просто сделать это в своем HTML:
<input type="text" id="myField" data-ng-model="someModel" data-search>
Ответ 2
На мой взгляд, лучший способ разработки компонента многократного использования - изолировать область действия и директивный контроллер. В вашем случае я не вижу вашей логики, поэтому я сделаю ее простой, просто изолирую область.
Ваш файл шаблона:
<div style="position: relative">
<a href role="button" class="btn x" style="display: none">×</a>
<input type="text" id="myField" data-ng-model="model">
</div>
JS:
angular.module('myApp', []).directive('search', function() {
return {
restrict: 'E',
scope:{
model:"=model"
},
link: function( scope, element, attrs ) {
// more code that not relevant to my question
},
templateUrl:url-to-your-template
};
});
Используйте его:
<search model="someModel"/>
Или просто:
<search />
Если вам нужно использовать его как атрибут, попробуйте:
JS:
angular.module('myApp', []).directive('search', function() {
return {
restrict: 'A',
scope:{
model:"=model"
},
replace:true,
link: function( scope, element, attrs ) {
// more code that not relevant to my question
},
templateUrl:url-to-your-template
};
});
Используйте его:
<div search model="someModel"/>
или просто:
<div search />