我是Angular的新手,并试图理解高级指令API - 我想使用指令元素属性在编译函数中重新创建指令模板。 但是当我没有模板集(或模板是空字符串)而不是访问隔离指令范围时,我访问父(控制器)范围。此外 - 这适用于Angular 1.1但不适用于1.2
这是HTML:
<div class="container" ng-app="app" ng-controller="AppController">
<sandbox title="Attribute Title"></sandbox>
</div>
JavaScript的:
var app = angular.module('app', [], function () {});
app.controller('AppController', function ($scope) {
$scope.title = "AppController title";
});
app.directive('sandbox', function ($log, $compile) {
return {
restrict: 'E',
scope: {
title: "@"
},
controller: function ($scope, $element, $attrs) {
$scope.title = "Directive Controller title";
},
template: '<h1>Template</h1>', // change it to: '' and Run, than change Angular to 1.2.x
compile: function (tElement, tAttrs) {
tElement.append('<h2> Title = {{ title }}</h2>');
}
}
});
当你运行它时,你得到:
模板
标题=属性标题
但是当你将模板更改为空字符串时,你会得到Angular 1.2:
标题= AppController标题
使用Angular 1.1.1:
标题=属性标题
我的问题:
为什么设置模板时访问范围与未设置模板时存在差异?
为什么Angular 1.1和1.2之间存在差异(bug? - 没有'template'的指令,isoleted范围接受控制器范围而非指令范围)?
如何在编译函数中构建访问Angular 1.2中隔离范围而非父范围的模板?
为什么指令控制器功能不会使用$ scope.title =“...”更改'title' - 但是在'link'函数'title'中调试'scope'参数时,'title'值为'Directive Controler Title'但它内部(在哪里寻找它)绑定isoleted范围'属性值'?
这是JSFiddle:http://jsfiddle.net/yoorek/zQ66L/4/
答案 0 :(得分:7)
你已经遇到了1.2中发生的重大变化(以及使用“@”的怪癖)。
1)当你的模板是``Angular时,看不到要应用隔离范围的模板。这是1.2问题的原因在于你的第二个问题的答案。
2)这是1.2破坏性更改的结果 - make isolate scope truly isolate:
隔离范围现在仅适用于请求它的isolate指令及其模板。
因此,如果没有模板,您将附加到隔离范围之外的元素 来自https://github.com/angular/angular.js/issues/4889:
因为我们无法区分最初在html文件中的标记 和编译函数中添加的标记也是后者 没有得到隔离范围。
和
...编译函数中的附加标记应该替换为using 模板属性。
这个想法是模板属性也可以是一个函数。如果它 是一个,它将获取编译元素和编译属性 参数。
3)如上所述,Angular(1.2之后)实际上是在尝试推动您使用模板而不是编译功能。您最好的选择可能是以您使用编译的方式使用模板功能。或者,您可以使用带有$compile
的链接函数 - 但这可能会增加不必要的复杂性。
通过在编译函数中附加,你实际上只是添加到模板中,所以它可以解决这个问题。
4)这与@
的工作方式有关。来自Angulars guide to scopes:
在链接中使用attrs。$ observe('attr_name',function(value){...} 函数获取隔离范围属性的插值 使用'@'表示法。例如,如果我们在链接中有这个 function - attrs。$ observe('interpolated',function(value){...} - value将设置为11.(scope.interpolatedProp未定义 连接功能。相比之下,scope.twowayBindingProp定义于 链接函数,因为它使用'='表示法。)