在 Angular 中结合隔离范围访问父控制器数据
Accessing parent controller data in combination with isolated scope in Angular
先是代码,再是解释:
index.html
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js@*" data-semver="1.3.7" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.7/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="app.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<my-directive data="1" />
<my-directive data="2" />
</div>
</body>
</html>
app.js
angular.module("myApp", []).directive("myDirective", function ($parent) {
return {
restrict: "E",
scope: {
data: "@",
},
template: function(element, attrs){
switch(attrs.data){
case '1':
return '<h3>'+ $parent.stringForDirective1 + '</h3>';
case '2':
return '<h3>'+ $parent.stringForDirective2 + '</h3>';
}
}
};
}).controller('myCtrl',function($scope){
$scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
$scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
});
现在进行说明。如果我要在我的指令上设置 'scope: false',我可以轻松访问控制器的数据,因为指令位于其范围内。但是,根据我的理解,为了将 HTML 属性中的任何值与自定义指令一起使用,必须将整个指令放入一个独立的范围内。
我想将 HTML 属性用于 return 使用父控制器数据的模板。
在使用 'scope: false' 的同时能够传入自定义 HTML 属性时,如何获得控制器数据的好处?
$parent 示例不起作用,我只是添加它来展示我一直在思考解决方案的方式,我认为它清楚地表明了我的意图。
指令可以具有三种可能的作用域模式:
- 隔离范围(范围:{})
- 子范围(范围:true)
- 继承范围(范围:false)
根据指令的需要,这些范围模式中的任何一种都有效。
如果你想创建一个具有隔离范围的指令,那么你可以通过元素的属性将模型传递到你的指令的隔离范围:
scope: {
modelA: '=', // model binding
modelB: '@', // string binding
modelC: '&' // method binding in parent scope
}
属性
<div directive model-a="user" model-b="hello {{ user.name }}" model-c="addUser(user)"></div>
示例(不是理想的指令实现,但用于展示如何通过属性将模型传递到隔离范围)
angular.module("myApp", []).directive("myDirective", function ($parent) {
return {
restrict: "E",
scope: {
data: "@",
stringForDirective1: '=?',
stringForDirective2: '=?'
},
template: '<h3 ng-if="data = '1'">{{stringForDirective1 }}</h3><h3 ng-if="data = '2'">{{stringForDirective2 }}</h3>'
};
}).controller('myCtrl',function($scope){
$scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
$scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
});
HTML
<body ng-app="myApp">
<div ng-controller="myCtrl">
<my-directive data="1" string-for-directive1="stringForDirective1" />
<my-directive data="2" string-for-directive2="stringForDirective2" />
</div>
</body>
不确定为什么要注入 $parent
依赖项。我希望那是你用来展示你的想法的那个:The $parent example does not work, I simply added it to show the way I've been thinking towards a solution, and I think it shows my intent clearly.
无论如何,你不需要这些。要使其全部正常工作,只需摆脱该依赖性,不要将父作用域值连接到模板中,而是让 Angular 在编译模板后处理它(使用双花括号进行绑定) :
switch(attrs.data){
case '1':
return '<h3>{{$parent.stringForDirective1}}</h3>';
case '2':
return '<h3>{{$parent.stringForDirective2}}</h3>';
}
那仍然会寻找 scope.$parent
,这正是您想要的。
在此处查看完整的工作示例:http://plnkr.co/edit/pW5G2Yy4SelW5DxKBMqW?p=preview
或此处,作为片段:
angular.module("myApp", [])
.directive("myDirective", function() {
return {
restrict: "E",
scope: {
data: "@",
},
template: function(element, attrs) {
switch (attrs.data) {
case '1':
return '<h3>{{$parent.stringForDirective1}}</h3>';
case '2':
return '<h3>{{$parent.stringForDirective2}}</h3>';
}
}
};
})
.controller('myCtrl', function($scope) {
$scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
$scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<my-directive data="1"></my-directive>
<my-directive data="2"></my-directive>
</div>
</body>
注意:必须指定指令结束标记,因为 shorthand 版本只读取第一个指令(Plunker 说你的指令元素上不允许尾随斜线),请参见此处:http://plnkr.co/edit/Qt0z0poU0ogoQq4C9a3n?p=preview
先是代码,再是解释:
index.html
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js@*" data-semver="1.3.7" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.7/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="app.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<my-directive data="1" />
<my-directive data="2" />
</div>
</body>
</html>
app.js
angular.module("myApp", []).directive("myDirective", function ($parent) {
return {
restrict: "E",
scope: {
data: "@",
},
template: function(element, attrs){
switch(attrs.data){
case '1':
return '<h3>'+ $parent.stringForDirective1 + '</h3>';
case '2':
return '<h3>'+ $parent.stringForDirective2 + '</h3>';
}
}
};
}).controller('myCtrl',function($scope){
$scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
$scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
});
现在进行说明。如果我要在我的指令上设置 'scope: false',我可以轻松访问控制器的数据,因为指令位于其范围内。但是,根据我的理解,为了将 HTML 属性中的任何值与自定义指令一起使用,必须将整个指令放入一个独立的范围内。
我想将 HTML 属性用于 return 使用父控制器数据的模板。
在使用 'scope: false' 的同时能够传入自定义 HTML 属性时,如何获得控制器数据的好处?
$parent 示例不起作用,我只是添加它来展示我一直在思考解决方案的方式,我认为它清楚地表明了我的意图。
指令可以具有三种可能的作用域模式:
- 隔离范围(范围:{})
- 子范围(范围:true)
- 继承范围(范围:false)
根据指令的需要,这些范围模式中的任何一种都有效。
如果你想创建一个具有隔离范围的指令,那么你可以通过元素的属性将模型传递到你的指令的隔离范围:
scope: {
modelA: '=', // model binding
modelB: '@', // string binding
modelC: '&' // method binding in parent scope
}
属性
<div directive model-a="user" model-b="hello {{ user.name }}" model-c="addUser(user)"></div>
示例(不是理想的指令实现,但用于展示如何通过属性将模型传递到隔离范围)
angular.module("myApp", []).directive("myDirective", function ($parent) {
return {
restrict: "E",
scope: {
data: "@",
stringForDirective1: '=?',
stringForDirective2: '=?'
},
template: '<h3 ng-if="data = '1'">{{stringForDirective1 }}</h3><h3 ng-if="data = '2'">{{stringForDirective2 }}</h3>'
};
}).controller('myCtrl',function($scope){
$scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
$scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
});
HTML
<body ng-app="myApp">
<div ng-controller="myCtrl">
<my-directive data="1" string-for-directive1="stringForDirective1" />
<my-directive data="2" string-for-directive2="stringForDirective2" />
</div>
</body>
不确定为什么要注入 $parent
依赖项。我希望那是你用来展示你的想法的那个:The $parent example does not work, I simply added it to show the way I've been thinking towards a solution, and I think it shows my intent clearly.
无论如何,你不需要这些。要使其全部正常工作,只需摆脱该依赖性,不要将父作用域值连接到模板中,而是让 Angular 在编译模板后处理它(使用双花括号进行绑定) :
switch(attrs.data){
case '1':
return '<h3>{{$parent.stringForDirective1}}</h3>';
case '2':
return '<h3>{{$parent.stringForDirective2}}</h3>';
}
那仍然会寻找 scope.$parent
,这正是您想要的。
在此处查看完整的工作示例:http://plnkr.co/edit/pW5G2Yy4SelW5DxKBMqW?p=preview
或此处,作为片段:
angular.module("myApp", [])
.directive("myDirective", function() {
return {
restrict: "E",
scope: {
data: "@",
},
template: function(element, attrs) {
switch (attrs.data) {
case '1':
return '<h3>{{$parent.stringForDirective1}}</h3>';
case '2':
return '<h3>{{$parent.stringForDirective2}}</h3>';
}
}
};
})
.controller('myCtrl', function($scope) {
$scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
$scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<my-directive data="1"></my-directive>
<my-directive data="2"></my-directive>
</div>
</body>
注意:必须指定指令结束标记,因为 shorthand 版本只读取第一个指令(Plunker 说你的指令元素上不允许尾随斜线),请参见此处:http://plnkr.co/edit/Qt0z0poU0ogoQq4C9a3n?p=preview