简体   繁体   English

使用controllerAs语法通过指令$ watch更改父控制器模型

[英]Change parent controller model through directive $watch using controllerAs syntax

I'm new to controllerAs syntax of angular and just trying to understand how it works with directive. 我是控制器的新手作为angular的语法,只是试图理解它如何与指令一起工作。 I've created one directive for password validation. 我已经为密码验证创建了一个指令。 I want to make some flag true based on conditions and those will be used in parent template for displaying error messages. 我想根据条件使一些标志为真,并且这些将在父模板中用于显示错误消息。 I'm not getting how can I achieve this! 我不知道怎么能实现这个目标!

JSFiddle 的jsfiddle

VIEW 视图

<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>

Directive 指示

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() {

    }
});

Specially I want to understand why and how below watch is working fine! 特别想了解为什么以及如何在手表下工作正常!

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

This is just for learning purpose so please explain how controllerAs and bindToController works! 这仅用于学习目的,请解释controllerAsbindToController如何工作!

your example is kinda messy but ill try to answer your questions. 你的例子有点乱,但生病了,试着回答你的问题。

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

this works because your directive is using SAME scope and variables on it as its parent controller. 这是有效的,因为您的指令使用SAME作用域和变量作为其父控制器。

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

this is undefined because you are using controllerAs on SAME scope so new variable called dvm is not created and all your dvm controller variables are initialized on parent scope. this是未定义的,因为您在SAME范围上使用controllerAs,因此不会创建名为dvm新变量,并且所有dvm控制器变量都在父范围内初始化。

That means that you dont need to 'inject' person controller into directive because you already have controller instance on directive scope. 这意味着你不需要将人控制器“注入”指令,因为你已经在指令范围内有控制器实例。 So just set your variable 'showMsg' like this and it will work like a magic! 所以只需像这样设置你的变量'showMsg',它就像魔术一样!

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

I made a fiddle for you: JSFiddle 我为你做了一个小提琴: JSFiddle

I know this was not part of your question, I will get to it, but using directive 'ng-controller' is an anti-pattern. 我知道这不是你问题的一部分,我会接受它,但使用指令'ng-controller'是一种反模式。 If if are interested why I can explain in a separate post but in short it makes code much harder to follow. 如果有兴趣为什么我可以在一个单独的帖子中解释,但简而言之,它使代码更难以遵循。

Now, to get to the heart of your question. 现在,了解你的问题的核心。

From reading the Angular documentation for bindToController it would appear that if you are not also creating an isolated scope, ie scope: true or scope: {} it does not do anything. 通过阅读bindToController的Angular文档,看起来如果你还没有创建一个独立的范围,即scope: truescope: {}它不会做任何事情。

Personally I have never used it before and does not seem particularly useful. 我个人以前从未使用它,似乎没有特别有用。

Using ng-controller is in essence adding a property to the current scope with that controller object. 使用ng-controller本质上是使用该控制器对象向当前作用域添加属性。

So: 所以:

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

Is effectively saying, (in a contrived way): 有效地说,(以一种人为的方式):

$scope.person = new PersonCtrl();

Your directive passwordValidator which is using the controllerAs syntax within it is basically doing: 你在其中使用controllerAs语法的指令passwordValidator基本上是这样做的:

$scope.dvm= new PasswordCtrl();

In this case you effectively have a scope object that looks like: 在这种情况下,您实际上有一个范围对象,如下所示:

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

Your person controller and dvm controller are sibling objects. 你的person控制器和dvm控制器是兄弟对象。 Within your passwordValidator directive you are requiring in its controller, which is the dvm object. 在您的passwordValidator指令中,您需要在其控制器中,即dvm对象。 Using that dvm object are you setting person.showMsg which is the same as doing: 使用该dvm对象是设置person.showMsg ,它与执行以下操作相同:

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

The dvm object does not have a way to access the person object, as they are siblings, on the $scope. dvm对象没有办法在$ scope上访问person对象,因为它们是兄弟姐妹。 So you need to use the $scope itself to access the person object. 因此,您需要使用$ scope本身来访问person对象。 You would need to do: 你需要这样做:

$scope.person.showMsg = <value>

Although this assumes that person exists on the scope, which is a dangerous assumption. 虽然这假设person存在于范围内,这是一个危险的假设。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM