从指令中包装源元素的更好方法是什么?

And*_*ion 13 html javascript angularjs

我正在编写一个指令(使用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>
Run Code Online (Sandbox Code Playgroud)

我到目前为止的指令:

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
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

我最终得到的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>
Run Code Online (Sandbox Code Playgroud)

这就是我所追求的,但我想理想地模拟这两个新元素,并从我的link函数中抽象出DOM操作.

我觉得可能有更好的方法来使用其中一个或两个replace/ templatetransclude选项,但我不确定如何保留和使用源元素(包含其所有属性和数据绑定)与这些选项之一.

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

Ada*_*dam 6

可能正是您正在寻找的翻译.这是一些更新的代码.

模板:

<div style="position: relative">
  <a href role="button" class="btn x" style="display: none">&times;</a>
  <div ng-transclude></div>
</div>
Run Code Online (Sandbox Code Playgroud)

指示:

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
  };
});
Run Code Online (Sandbox Code Playgroud)

HTML:

<div data-search>
  <input type="text" id="myField" data-ng-model="someModel">
</div>
Run Code Online (Sandbox Code Playgroud)

你应该只使用指令中的模板或templateUrl中的一个,我倾向于templateURL因为我讨厌字符串模板.

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

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

如果你这样做,可以考虑更多:

transclude: 'element'
Run Code Online (Sandbox Code Playgroud)

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

<input type="text" id="myField" data-ng-model="someModel" data-search>
Run Code Online (Sandbox Code Playgroud)


Kha*_* TO 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>
Run Code Online (Sandbox Code Playgroud)

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
  };
});
Run Code Online (Sandbox Code Playgroud)

用它:

<search model="someModel"/>
Run Code Online (Sandbox Code Playgroud)

要不就:

<search />
Run Code Online (Sandbox Code Playgroud)

如果您需要将其用作属性,请尝试:

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
  };
});
Run Code Online (Sandbox Code Playgroud)

用它:

<div search model="someModel"/>
Run Code Online (Sandbox Code Playgroud)

要不就:

<div search />
Run Code Online (Sandbox Code Playgroud)