【问题标题】:Change parent controller model through directive $watch using controllerAs syntax使用 controllerAs 语法通过指令 $watch 更改父控制器模型
【发布时间】:2017-02-07 06:59:51
【问题描述】:

我是新来的控制器作为角度的语法,只是想了解它是如何与指令一起工作的。我创建了一个密码验证指令。我想根据条件使一些标志为真,这些标志将在父模板中用于显示错误消息。我不明白我怎么能做到这一点!

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的工作原理!

【问题讨论】:

  • 您的要求是什么?解释或解决方案
  • 解决方案,详细说明其工作原理。
  • 在 angularjs 中使用指令时(或仅使用 angularjs 时),了解摘要生命周期很重要,这基本上是对范围模型和视图之间更改的脏检查。这是使我们的生活更轻松的核心功能。这是我读过的关于该主题的最佳文章sitepoint.com/understanding-angulars-apply-digest
  • 小提琴工作正常! msg true 和 false 有一些条件变化。那么你的问题是什么?
  • 你能给我工作小提琴链接吗?你有什么改变?

标签: javascript angularjs angular-directive


【解决方案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 存在于作用域上,但这是一个危险的假设。

【讨论】:

    【解决方案2】:

    你的例子有点乱,但我试图回答你的问题。

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

    这是有效的,因为您的指令使用相同的范围和变量作为其父控制器。

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

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

    这意味着您不需要将人员控制器“注入”到指令中,因为您已经在指令范围内拥有控制器实例。所以只要像这样设置你的变量'showMsg',它就会像魔术一样工作!

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-08
      • 1970-01-01
      • 1970-01-01
      • 2016-03-17
      • 1970-01-01
      • 2014-12-27
      • 1970-01-01
      • 2016-04-04
      相关资源
      最近更新 更多