13

我正在编写一个指令(使用 AngularJS 1.2.0-rc2,如果这很重要),它将一个“清除”按钮(想想浏览器为<input type="search">元素添加的“x”按钮)添加到<input>.

由于“清除”按钮是从指令中注入的并且是绝对定位的,我想将现有和新添加的“清除”按钮包含在一个必须确保正确定位<input>“清除”按钮的包装元素中。position: relative

声明的 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's 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/templatetransclude选项中的一个或两个,但我不确定如何保留和使用源元素(及其所有属性和数据绑定)与这些选项中的任何一个。

另请注意,即使我的示例ng-model在源元素上定义了,也应视为可选。我还想将指令限制为属性(restrict: 'A')。

4

2 回答 2

6

嵌入可能是您正在寻找的。这是一些更新的代码。

模板:

<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>

您应该只在指令中使用 template 或 templateUrl 之一,我会倾向于 templateURL 因为我讨厌字符串模板。

如果您需要更多逻辑,您仍然可以包含链接功能。

replace 属性将完全替换您应用该元素的现有 DOM 元素,而保留此属性将保留该元素并将您的模板放入其中。由您决定如何配置。

再想一想,如果你这样做:

transclude: 'element'

您可以在 HTML 中执行此操作:

<input type="text" id="myField" data-ng-model="someModel" data-search>
于 2013-10-11T14:47:46.360 回答
3

在我看来,设计可重用组件的更好方法是隔离范围和指令控制器。在您的情况下,我看不到您的逻辑,因此我将仅使用隔离范围使其变得简单。

您的模板文件:

<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's 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's not relevant to my question
    },
    templateUrl:url-to-your-template
  };
});

用它:

<div search model="someModel"/>

要不就:

<div search />
于 2013-10-11T14:43:56.177 回答