使用 controllerAs 语法通过指令 $watch 更改父控制器模型
Change parent controller model through directive $watch using controllerAs syntax
我是 angular 的 controllerAs 语法的新手,只是想了解它如何与指令一起使用。我已经为密码验证创建了一个指令。我想根据条件使一些标志为真,这些标志将在父模板中用于显示错误消息。我不知道如何实现!
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>
指令
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");
});
这只是为了学习目的,所以请解释 controllerAs
和 bindToController
是如何工作的!
你的例子有点乱,但我会尽量回答你的问题。
// 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
控制器变量都在父范围内初始化。
这意味着你不需要 'inject' person controller 进入指令,因为你已经在指令范围内有控制器实例。因此,只需像这样设置您的变量 'showMsg',它就会像魔术一样工作!
if(newVal!='') {
scope.person.showMsg = true;
} else {
scope.person.showMsg = false;
}
console.log(scope.person.showMsg);
我给你做了一个fiddle:JSFiddle
我知道这不是你问题的一部分,我会解决的,但是使用指令 'ng-controller' 是一种反模式。如果有兴趣,为什么我可以单独解释 post 但简而言之,这会使代码更难理解。
现在,进入问题的核心。
通过阅读 bindToController
的 Angular 文档可以看出,如果您没有同时创建一个独立的作用域,即 scope: true
或 scope: {}
它不会做任何东西。
就我个人而言,我以前从未使用过它,而且似乎不是特别有用。
使用 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
,但这是一个危险的假设。
我是 angular 的 controllerAs 语法的新手,只是想了解它如何与指令一起使用。我已经为密码验证创建了一个指令。我想根据条件使一些标志为真,这些标志将在父模板中用于显示错误消息。我不知道如何实现!
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>
指令
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");
});
这只是为了学习目的,所以请解释 controllerAs
和 bindToController
是如何工作的!
你的例子有点乱,但我会尽量回答你的问题。
// 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
控制器变量都在父范围内初始化。
这意味着你不需要 'inject' person controller 进入指令,因为你已经在指令范围内有控制器实例。因此,只需像这样设置您的变量 'showMsg',它就会像魔术一样工作!
if(newVal!='') {
scope.person.showMsg = true;
} else {
scope.person.showMsg = false;
}
console.log(scope.person.showMsg);
我给你做了一个fiddle:JSFiddle
我知道这不是你问题的一部分,我会解决的,但是使用指令 'ng-controller' 是一种反模式。如果有兴趣,为什么我可以单独解释 post 但简而言之,这会使代码更难理解。
现在,进入问题的核心。
通过阅读 bindToController
的 Angular 文档可以看出,如果您没有同时创建一个独立的作用域,即 scope: true
或 scope: {}
它不会做任何东西。
就我个人而言,我以前从未使用过它,而且似乎不是特别有用。
使用 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
,但这是一个危险的假设。