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

时间:2013-10-11 14:26:10

标签: javascript html angularjs

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

由于“清除”按钮是从指令注入并且绝对定位的,我想在包含元素{{1}中包含现有的<input>和新添加的“clear”按钮。确保正确定位“清除”按钮。

声明的HTML如下所示:

position: relative

我到目前为止的指令:

<input type="text" id="myField" data-ng-model="someModel" data-search>

我最终得到的HTML是

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
    }
  };
});

这就是我所追求的,但我想理想地模拟这两个新元素,并从我的<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 / replacetemplate选项中的一个或两个可能有更好的方法来解决这个问题,但我不确定如何保留和使用源元素(包含其所有属性和数据绑定)与这些选项之一。

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

2 个答案:

答案 0 :(得分: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>

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

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

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

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

transclude: 'element'

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

<input type="text" id="myField" data-ng-model="someModel" data-search>

答案 1 :(得分: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 />