AngularJS:Transcluded指令和对模型的访问

时间:2014-02-03 08:28:30

标签: javascript angularjs transclusion

我正在创建一个smart input指令,它将包装一个文本输入元素,并且需要访问input元素上的模型才能操作指令上的某些类。

因为输入元素可以是多种类型之一(文本,电子邮件,密码),我需要转换该指令并能够为每个类型添加不同类型的验证。

我遇到的问题(与互联网上的许多其他人一样)是范围继承。

以下是我目前的代码
HTML

<smart-input ng-model="username">
  <span ng-show="isTyping">{{ placeholder }}</span>
  <input type="text" name="username" ng-model="username" ng-minlength="4" ng-maxlength="20" required />
</smart-input>

JS

angular.module('myApp').directive('smartInput', function ($compile) {
  return {
    restrict: 'E',
    transclude: true,
    replace: true,
    scope: {
      model: '=ngModel'
    },
    template: '<div class="text-input" ng-class="{typing: isTyping}" ng-transclude>' +
              '</div>',
    link: function(scope, element, attrs) {
      scope.isTyping = false;

      scope.$watch('model', function(value) {
        console.log(value);
        scope.isTyping = value.length > 0;
      });
    }
  };
});

基本上,$ watch函数中的value是未定义的,所以很明显我没有这样做。

那么,如何将模型绑定到输入字段,同时让指令引用同一个对象并且能够watch它的值?

1 个答案:

答案 0 :(得分:0)

当您使用隔离范围进行转换时,您的范围没有父/子关系。它看起来像这样:

<controllerScope>
     <smartInputScope>
     <transcludedContentScope>

这就是为了访问smartInputScope的model属性,我们必须访问$$prevSibling.model在您的第一个示例中ng-model="username"有效,因为此范围继承自controllerScope,它正在访问父级的范围属性。

使用自定义转换检查我的解决方案:http://plnkr.co/edit/cV9urKJdcn4mKlpqPJTr?p=preview

app.directive('smartInput', function($compile) {
  return {
    restrict: 'E',
    transclude: true,
    replace: true,
    scope: {
      model: '=ngModel'
    },
    template: '<div class="text-input" ng-class="{typing: isTyping}">' +
      '</div>',
    compile: function(element, attr, linker) {
      return {
        pre: function(scope, element, attr) {
          linker(scope, function(clone) { //bind the scope your self
            element.append(clone); // add to DOM
          });
        },
        post: function postLink(scope, iElement, iAttrs) {
          scope.isTyping = false;

          scope.$watch('model', function(value) {
            console.log(value);
            scope.isTyping = value.length > 0;
          });
        }
      };
    }
  };
});

在html中,我不再需要$$prevSibling

<input type="text" name="username" ng-model="model" ng-minlength="4" ng-maxlength="20" required />