Подтвердить что ты не робот

Лучший способ обернуть исходный элемент из Директивы?

Я пишу Директиву (используя 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">&times;</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">&times;</a>
  <input type="text" id="myField" data-ng-model="someModel" data-search>
</div>

это то, что мне нужно, но я хотел бы идеально сфокусировать два новых элемента и абстрагировать манипуляции DOM из моей функции link.

Мне кажется, что есть лучший способ сделать это, используя либо или оба параметра replace/template и transclude, но я не уверен, как сохранить и использовать исходный элемент (со всеми его атрибуты и привязки данных) с любой из этих опций.

Также обратите внимание, что хотя мой образец имеет ng-model, определенный в исходном элементе, это следует считать необязательным. Я также хотел бы, чтобы директива ограничивалась атрибутами (restrict: 'A').

4b9b3361

Ответ 1

Заключение - это, вероятно, то, что вы ищете. Вот обновленный код.

Шаблон:

<div style="position: relative">
  <a href role="button" class="btn x" style="display: none">&times;</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">&times;</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 />