[英]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!
我不知道怎么能实现这个目标!
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! 这仅用于学习目的,请解释
controllerAs
和bindToController
如何工作!
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 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: true
或scope: {}
它不会做任何事情。
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.