使用controllerAs语法

时间:2016-09-29 05:24:40

标签: javascript angularjs angular-directive

我是控制器的新手作为angular的语法,只是试图理解它如何与指令一起工作。我已经为密码验证创建了一个指令。我想根据条件使一些标志为真,并且这些将在父模板中用于显示错误消息。我不知道怎么能实现这个目标!

JSFiddle

查看

<div ng-app="myapp">
    <fieldset ng-controller="PersonCtrl as person">
        <input name="emailID" type="text" ng-model="person.first" >
        <input name="pass" type="password" ng-model="person.pass" password-validator>
        <p ng-show="person.showMsg">Password validation message here.</p>
    </fieldset>
</div>

指令

myapp.directive('passwordValidator',function() {
        return {
        controller : PasswordCtrl,
      controllerAs : 'dvm',
      bindToController : true,
      require : ['ngModel','passwordValidator'],
      link : function(scope,ele,attrs,ctrls) {
        var person = ctrls[1];
        var ngModelCtrl = ctrls[0];

        scope.$watch(function() {
                    return ngModelCtrl.$modelValue;
        },function(newVal) {
          if(newVal!='') {
            person.showMsg = true;
          } else {
            person.showMsg = false;
          }
          console.log(person.showMsg);
        });
      }
    }

    function PasswordCtrl() {

    }
});
  

特别想知道为什么以及如何在手表下工作正常!

// Why this below is also working, can anyone explain what's going behind!! 
scope.$watch('person.pass',function(newVal) {
    console.log("Watch fires");
});

这仅用于学习目的,因此请说明controllerAsbindToController的工作原理!

2 个答案:

答案 0 :(得分:1)

你的例子有点乱,但生病了,试着回答你的问题。

// Why this below is also working, can anyone explain what's going behind!! 
scope.$watch('person.pass',function(newVal) {
    console.log("Watch fires");
});

这是有效的,因为您的指令使用SAME作用域和变量作为其父控制器。

this.checkDirCtrl = function() {
    console.log($scope.dvm);
}

this未定义,因为您在SAME范围上使用controllerAs,因此未创建名为dvm的新变量,并且所有dvm控制器变量都在父范围内初始化。

这意味着你不需要注射&#39; person controller into指令,因为你已经在指令范围内有控制器实例。所以只需设置你的变量&#39; showMsg&#39;像这样,它将像魔术一样工作!

      if(newVal!='') {
        scope.person.showMsg = true;
      } else {
        scope.person.showMsg = false;
      }
      console.log(scope.person.showMsg);

我为你做了一个小提琴:JSFiddle

答案 1 :(得分:1)

我知道这不是你问题的一部分,我会谈到它,但使用指令'ng-controller'是一种反模式。如果有兴趣为什么我可以在一个单独的帖子中解释,但简而言之,它使代码更难以遵循。

现在,了解你问题的核心。

通过阅读bindToController的Angular文档,如果您还没有创建一个孤立的范围,即scope: truescope: {},它似乎无法执行任何操作。

就我个人而言,我以前从未使用它,似乎没什么用处。

使用ng-controller本质上是使用该控制器对象向当前作用域添加属性。

所以:

<fieldset ng-controller="PersonCtrl as person">

有效地说,(以一种人为的方式):

$scope.person = new PersonCtrl();

在其中使用passwordValidator语法的指令controllerAs基本上是这样做的:

$scope.dvm= new PasswordCtrl();

在这种情况下,您实际上有一个范围对象,如下所示:

$scope = {
    person = new PersonCtrl(),
    dvm: new PasswordCtrl()
}

您的person控制器和dvm控制器是兄弟对象。 在您的passwordValidator指令中,您需要在其控制器中,即dvm对象。使用dvm对象设置person.showMsg与执行操作相同:

$scope.dvm.person.showMsg = <value>

dvm对象没有办法在$ scope上访问person对象,因为它们是兄弟姐妹。因此,您需要使用$ scope本身来访问person对象。你需要这样做:

$scope.person.showMsg = <value>

虽然这假设范围内存在person,这是一个危险的假设。