2

我正在编写一个非常简单的指令:它应该将一个输入元素包装在一个 div 中。我为此使用了嵌入。问题是它出于某种原因破坏了 ng-model。请参阅此 plunker 以获取完整代码:http ://plnkr.co/edit/tYTsVUbleZV1iG6eMgjo

我该怎么做才能使 ng-model 的行为符合预期?

指令代码

这是指令的代码:

testapp.directive('wrapInput', [function () {
   return {
      replace: true,
      transclude: 'element',
      template: '<div class="input-wrapper" ng-transclude></div>'
   };
}]);
4

3 回答 3

3

如果您将标记更改为如下所示

<div  wrap-input>
  <input type="text" ng-model="anObject.anotherValue"/>
</div>

然后你也可以使用

transclude: true // instead of transclude: 'element'

它工作得很好。我不能说为什么,但我之前在使用 transclude: 'element' 和 replace: true 时已经看到过这个问题。稍后我将不得不深入研究源代码以查看发生了什么。不管怎样,使用此解决方法生成的标记应该是相同的。

于 2013-10-16T19:27:49.663 回答
3

我想既然ng-repeat可以做到,那一定是可能的:

http://plnkr.co/edit/stf02iPNvNnlsx1dsFZx?p=preview

app.directive( 'wrapThisThing', [ '$compile', function( $compile ) {
  return {
    restrict: 'A',
    transclude: 'element',
    link: function( scope, element, attrs, ctrl, transclude ) {

      // Compile a new DOM context and bind it to our scope.
      var template = angular.element( '<div class="wrap">' );
      var context = $compile( template )( scope );

      transclude( function( clone, theScope ) {
        // To make this work, we need to remove our directive attribute from
        // the clone before compiling it back to its original scope. If we
        // don't do this, the compiler will re-evaluate our directive, creating
        // an infinite loop.

        // We can use the $attr property to figure out what attribute variation
        // was used (ie. data-wrap-this-thing, x-wrap-this-thing, wrap:this:thing,
        // etc.).
        // See more about attribute normalization:
        // http://www.bennadel.com/blog/2648-inspecting-attribute-normalization-within-directives-in-angularjs.htm

        clone.removeAttr( attrs.$attr.wrapThisThing );

        // Compile the transcluded element and bind it to its own scope. Then
        // append it to our new context.
        context.append( $compile( clone )( theScope ) );
      });
      element.replaceWith( context );
    }
  };
}]);
于 2014-07-30T03:05:34.427 回答
0

我相信你必须为你的指令定义一个隔离范围,也许还有一个控制器。像这样的东西:

return {
  replace: true,
  transclude: 'element',
  scope: {},
  controller: function(scope){},
  template: '<div class="input-wrapper" ng-transclude></div>'

};

然后,您只需要将指令的范围绑定到父范围。不幸的是,我还不能让它在你的 plnkr 中工作,但是当我这样做时我会编辑我的答案。

于 2013-10-16T19:28:41.297 回答