col*_*lin 323 angularjs angularjs-directive
我正在寻找任何方式访问指令中的"父"范围.范围,转换,要求的任何组合,从上面传递变量(或范围本身)等.我完全愿意向后弯腰,但我想避免一些完全hacky或不可维护的东西.例如,我知道我现在可以通过$scope从preLink参数中获取并迭代它的$sibling范围来找到概念性的"父".
我真正想要的是能够$watch在父范围内表达.如果我能做到这一点,那么我可以完成我在这里要做的事情:
AngularJS - 如何使用变量渲染部分?
重要的一点是,该指令必须可以在同一父范围内重复使用.因此默认行为(范围:false)对我不起作用.我需要每个指令实例的单独范围,然后我需要$watch一个存在于父范围内的变量.
代码示例值1000个单词,因此:
app.directive('watchingMyParentScope', function() {
return {
require: /* ? */,
scope: /* ? */,
transclude: /* ? */,
controller: /* ? */,
compile: function(el,attr,trans) {
// Can I get the $parent from the transclusion function somehow?
return {
pre: function($s, $e, $a, parentControl) {
// Can I get the $parent from the parent controller?
// By setting this.$scope = $scope from within that controller?
// Can I get the $parent from the current $scope?
// Can I pass the $parent scope in as an attribute and define
// it as part of this directive's scope definition?
// What don't I understand about how directives work and
// how their scope is related to their parent?
},
post: function($s, $e, $a, parentControl) {
// Has my situation improved by the time the postLink is called?
}
}
}
};
});
Run Code Online (Sandbox Code Playgroud)
Mar*_*cok 637
请参阅AngularJS中范围原型/原型继承的细微差别是什么?
总结一下:指令访问其parent($parent)范围的方式取决于指令创建的范围类型:
default(scope: false) - 该指令不创建新范围,因此这里没有继承.该指令的作用域与父/容器的作用域相同.在链接功能中,使用第一个参数(通常scope).
scope: true - 该指令创建一个新的子作用域,它原型继承自父作用域.在父作用域上定义的属性可用于指令scope(因为原型继承).只要注意写入原始范围属性 - 这将在指令范围上创建一个新属性(隐藏/隐藏同名的父范围属性).
scope: { ... } - 该指令创建一个新的隔离/隔离范围.它没有原型继承父作用域.您仍然可以使用父访问范围$parent,但通常不建议这样做.相反,应指定的父范围属性(和/或功能)的指令经由相同的元件上的附加属性,在使用该指令,使用需要=,@和&表示法.
transclude: true - 该指令创建一个新的"transcluded"子作用域,它原型继承自父作用域.如果该指令还创建了隔离范围,则transcluded和隔离范围是兄弟.$parent每个范围的属性引用相同的父范围.
Angular v1.3 update:如果该指令还创建了隔离范围,则transcluded范围现在是隔离范围的子代.被抄袭和隔离的范围不再是兄弟姐妹.$parenttranscluded范围的属性现在引用了隔离范围.
以上链接包含所有4种类型的示例和图片.
您无法访问指令编译函数中的作用域(如此处所述:https://github.com/angular/angular.js/wiki/Understanding-Directives).您可以在链接功能中访问指令的范围.
观看:
对于1.和2.上面:通常你通过属性指定指令需要哪个父属性,然后$ watch it:
<div my-dir attr1="prop1"></div>
Run Code Online (Sandbox Code Playgroud)
scope.$watch(attrs.attr1, function() { ... });
Run Code Online (Sandbox Code Playgroud)
如果您正在观看对象属性,则需要使用$ parse:
<div my-dir attr2="obj.prop2"></div>
Run Code Online (Sandbox Code Playgroud)
var model = $parse(attrs.attr2);
scope.$watch(model, function() { ... });
Run Code Online (Sandbox Code Playgroud)
对于3. above(隔离范围),使用@或=表示法观察您给出指令属性的名称:
<div my-dir attr3="{{prop3}}" attr4="obj.prop4"></div>
Run Code Online (Sandbox Code Playgroud)
scope: {
localName3: '@attr3',
attr4: '=' // here, using the same name as the attribute
},
link: function(scope, element, attrs) {
scope.$watch('localName3', function() { ... });
scope.$watch('attr4', function() { ... });
Run Code Online (Sandbox Code Playgroud)
Yog*_*are 50
访问控制器方法意味着从指令控制器/链接/范围访问父作用域上的方法.
如果指令是共享/继承父作用域,则只需调用父作用域方法就可以了.
当您想要从Isolated指令范围访问父范围方法时,需要做更多的工作.
从隔离的指令范围调用父作用域方法或观察父作用域变量(特别是选项#6),几乎没有选项(可能比下面列出的更多).
请注意,我link function在这些示例中使用过但您可以directive controller根据需要使用.
选项1. 通过Object文字和指令html模板
index.html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<p> Directive Content</p>
<sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged(selectedItems)" items="items"> </sd-items-filter>
<P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}} </p>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
itemfilterTemplate.html
<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" ng-change="selectedItemsChanged({selectedItems:selectedItems})" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
<option>--</option>
</select>
Run Code Online (Sandbox Code Playgroud)
app.js
var app = angular.module('plunker', []);
app.directive('sdItemsFilter', function() {
return {
restrict: 'E',
scope: {
items: '=',
selectedItems: '=',
selectedItemsChanged: '&'
},
templateUrl: "itemfilterTemplate.html"
}
})
app.controller('MainCtrl', function($scope) {
$scope.name = 'TARS';
$scope.selectedItems = ["allItems"];
$scope.selectedItemsChanged = function(selectedItems1) {
$scope.selectedItemsReturnedFromDirective = selectedItems1;
}
$scope.items = [{
"id": "allItems",
"name": "All Items",
"order": 0
}, {
"id": "CaseItem",
"name": "Case Item",
"model": "PredefinedModel"
}, {
"id": "Application",
"name": "Application",
"model": "Bank"
}]
});
Run Code Online (Sandbox Code Playgroud)
工作plnkr:http://plnkr.co/edit/rgKUsYGDo9O3tewL6xgr?p = preview
选项#2.通过Object文字和指令链接/范围
index.html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<p> Directive Content</p>
<sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged(selectedItems)" items="items"> </sd-items-filter>
<P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}} </p>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
itemfilterTemplate.html
<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;"
ng-change="selectedItemsChangedDir()" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
<option>--</option>
</select>
Run Code Online (Sandbox Code Playgroud)
app.js
var app = angular.module('plunker', []);
app.directive('sdItemsFilter', function() {
return {
restrict: 'E',
scope: {
items: '=',
selectedItems: '=',
selectedItemsChanged: '&'
},
templateUrl: "itemfilterTemplate.html",
link: function (scope, element, attrs){
scope.selectedItemsChangedDir = function(){
scope.selectedItemsChanged({selectedItems:scope.selectedItems});
}
}
}
})
app.controller('MainCtrl', function($scope) {
$scope.name = 'TARS';
$scope.selectedItems = ["allItems"];
$scope.selectedItemsChanged = function(selectedItems1) {
$scope.selectedItemsReturnedFromDirective = selectedItems1;
}
$scope.items = [{
"id": "allItems",
"name": "All Items",
"order": 0
}, {
"id": "CaseItem",
"name": "Case Item",
"model": "PredefinedModel"
}, {
"id": "Application",
"name": "Application",
"model": "Bank"
}]
});
Run Code Online (Sandbox Code Playgroud)
工作plnkr:http://plnkr.co/edit/BRvYm2SpSpBK9uxNIcTa?p=preview
选项#3.通过Function参考和指令html模板
index.html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<p> Directive Content</p>
<sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged" items="items"> </sd-items-filter>
<P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnFromDirective}} </p>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
itemfilterTemplate.html
<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;"
ng-change="selectedItemsChanged()(selectedItems)" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
<option>--</option>
</select>
Run Code Online (Sandbox Code Playgroud)
app.js
var app = angular.module('plunker', []);
app.directive('sdItemsFilter', function() {
return {
restrict: 'E',
scope: {
items: '=',
selectedItems:'=',
selectedItemsChanged: '&'
},
templateUrl: "itemfilterTemplate.html"
}
})
app.controller('MainCtrl', function($scope) {
$scope.name = 'TARS';
$scope.selectedItems = ["allItems"];
$scope.selectedItemsChanged = function(selectedItems1) {
$scope.selectedItemsReturnFromDirective = selectedItems1;
}
$scope.items = [{
"id": "allItems",
"name": "All Items",
"order": 0
}, {
"id": "CaseItem",
"name": "Case Item",
"model": "PredefinedModel"
}, {
"id": "Application",
"name": "Application",
"model": "Bank"
}]
});
Run Code Online (Sandbox Code Playgroud)
工作plnkr:http://plnkr.co/edit/Jo6FcYfVXCCg3vH42BIz?p =preview
第4个选项.通过函数引用和指令链接/范围
index.html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<p> Directive Content</p>
<sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged" items="items"> </sd-items-filter>
<P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}} </p>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
itemfilterTemplate.html
<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" ng-change="selectedItemsChangedDir()" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
<option>--</option>
</select>
Run Code Online (Sandbox Code Playgroud)
app.js
var app = angular.module('plunker', []);
app.directive('sdItemsFilter', function() {
return {
restrict: 'E',
scope: {
items: '=',
selectedItems: '=',
selectedItemsChanged: '&'
},
templateUrl: "itemfilterTemplate.html",
link: function (scope, element, attrs){
scope.selectedItemsChangedDir = function(){
scope.selectedItemsChanged()(scope.selectedItems);
}
}
}
})
app.controller('MainCtrl', function($scope) {
$scope.name = 'TARS';
$scope.selectedItems = ["allItems"];
$scope.selectedItemsChanged = function(selectedItems1) {
$scope.selectedItemsReturnedFromDirective = selectedItems1;
}
$scope.items = [{
"id": "allItems",
"name": "All Items",
"order": 0
}, {
"id": "CaseItem",
"name": "Case Item",
"model": "PredefinedModel"
}, {
"id": "Application",
"name": "Application",
"model": "Bank"
}]
});
Run Code Online (Sandbox Code Playgroud)
工作plnkr:http://plnkr.co/edit/BSqx2J1yCY86IJwAnQF1?p = preview
选项#5:通过ng-model和双向绑定,您可以更新父范围变量..因此,在某些情况下,您可能不需要调用父作用域函数.
index.html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<p> Directive Content</p>
<sd-items-filter ng-model="selectedItems" selected-items-changed="selectedItemsChanged" items="items"> </sd-items-filter>
<P style="color:red">Selected Items (in parent controller) set to: {{selectedItems}} </p>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
itemfilterTemplate.html
<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;"
ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
<option>--</option>
</select>
Run Code Online (Sandbox Code Playgroud)
app.js
var app = angular.module('plunker', []);
app.directive('sdItemsFilter', function() {
return {
restrict: 'E',
scope: {
items: '=',
selectedItems: '=ngModel'
},
templateUrl: "itemfilterTemplate.html"
}
})
app.controller('MainCtrl', function($scope) {
$scope.name = 'TARS';
$scope.selectedItems = ["allItems"];
$scope.items = [{
"id": "allItems",
"name": "All Items",
"order": 0
}, {
"id": "CaseItem",
"name": "Case Item",
"model": "PredefinedModel"
}, {
"id": "Application",
"name": "Application",
"model": "Bank"
}]
});
Run Code Online (Sandbox Code Playgroud)
工作plnkr:http://plnkr.co/edit/hNui3xgzdTnfcdzljihY?p =preview
选项#6:通过$watch和$watchCollection
它items在所有上述示例中是双向绑定,如果在父范围中修改了项目,则指令中的项目也将反映更改.
如果要从父作用域中观察其他属性或对象,可以使用$watch和执行$watchCollection以下操作
HTML
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{user}}!</p>
<p>directive is watching name and current item</p>
<table>
<tr>
<td>Id:</td>
<td>
<input type="text" ng-model="id" />
</td>
</tr>
<tr>
<td>Name:</td>
<td>
<input type="text" ng-model="name" />
</td>
</tr>
<tr>
<td>Model:</td>
<td>
<input type="text" ng-model="model" />
</td>
</tr>
</table>
<button style="margin-left:50px" type="buttun" ng-click="addItem()">Add Item</button>
<p>Directive Contents</p>
<sd-items-filter ng-model="selectedItems" current-item="currentItem" name="{{name}}" selected-items-changed="selectedItemsChanged" items="items"></sd-items-filter>
<P style="color:red">Selected Items (in parent controller) set to: {{selectedItems}}</p>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
脚本app.js
var app = angular.module('plunker',[]);
app.directive('sdItemsFilter', function() {
return {
restrict: 'E',
scope: {
name: '@',
currentItem: '=',
items: '=',
selectedItems: '=ngModel'
},
template: '<select ng-model="selectedItems" multiple="multiple" style="height: 140px; width: 250px;"' +
'ng-options="item.id as item.name group by item.model for item in items | orderBy:\'name\'">' +
'<option>--</option> </select>',
link: function(scope, element, attrs) {
scope.$watchCollection('currentItem', function() {
console.log(JSON.stringify(scope.currentItem));
});
scope.$watch('name', function() {
console.log(JSON.stringify(scope.name));
});
}
}
})
app.controller('MainCtrl', function($scope) {
$scope.user = 'World';
$scope.addItem = function() {
$scope.items.push({
id: $scope.id,
name: $scope.name,
model: $scope.model
});
$scope.currentItem = {};
$scope.currentItem.id = $scope.id;
$scope.currentItem.name = $scope.name;
$scope.currentItem.model = $scope.model;
}
$scope.selectedItems = ["allItems"];
$scope.items = [{
"id": "allItems",
"name": "All Items",
"order": 0
}, {
"id": "CaseItem",
"name": "Case Item",
"model": "PredefinedModel"
}, {
"id": "Application",
"name": "Application",
"model": "Bank"
}]
});
Run Code Online (Sandbox Code Playgroud)
您可以随时参考AngularJs文档以获取有关指令的详细说明.
Ste*_*rov 11
scope: false
transclude: false
Run Code Online (Sandbox Code Playgroud)
你将拥有相同的范围(与父元素)
$scope.$watch(...
Run Code Online (Sandbox Code Playgroud)
根据这两个选项范围和转换,有很多方法可以访问父作用域.
小智 8
这是我曾经使用过的一个技巧:创建一个"虚拟"指令来保存父范围并将其放在所需指令之外的某个位置.就像是:
module.directive('myDirectiveContainer', function () {
return {
controller: function ($scope) {
this.scope = $scope;
}
};
});
module.directive('myDirective', function () {
return {
require: '^myDirectiveContainer',
link: function (scope, element, attrs, containerController) {
// use containerController.scope here...
}
};
});
Run Code Online (Sandbox Code Playgroud)
然后
<div my-directive-container="">
<div my-directive="">
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
也许不是最优雅的解决方案,但它完成了工作.
| 归档时间: |
|
| 查看次数: |
258231 次 |
| 最近记录: |