我在angularJS应用程序中有两个自定义指令。一个充当父母,另一个充当孩子。我试图在child指令中访问父级的范围。但我没有得到理想的输出。
<div ng-controller="CountryCtrl">
{{myName}}
<div ng-controller="StateCtrl">
<state nameofthestate="'Tamilnadu'">
<city nameofthecity="'Chennai'"></city>
</state>
</div>
</div>
我的脚本看起来像
var app = angular.module("sampleApp",[]);
app.controller("CountryCtrl",function($scope){
$scope.myName = "India";
});
app.controller("StateCtrl",function($scope){
});
app.directive("state",function(){return {
restrict : 'E',
transclude: true,
scope : { myName : '=nameofthestate'},
template:"** {{myName}} is inside {{$parent.myName}}<br/><ng-transclude></ng-transclude>"
}});
app.directive("city",function(){return {
restrict : 'E',
require:'^state',
scope : { myName : '=nameofthecity'},
template:"**** {{myName}} is inside {{$parent.myName}} which is in {{$parent.$parent.myName }}<br/> "
}});
https://jsbin.com/nozuri/edit?html,js,output
中提供的相应JSFiddle我得到的输出是
India
** Tamilnadu is inside India
**** Chennai is inside India which is in Tamilnadu
,预期输出为
India
** Tamilnadu is inside India
**** Chennai is inside Tamilnadu which is in India
任何人都可以教育我在这里做错了吗?
答案 0 :(得分:28)
city指令$ parent是一个transcluded状态指令。
state指令的transcluded范围是继承状态指令的$ parent,这是控制器,因此$ parent.MyName = India。
transcluded范围的$ parent是状态指令隔离范围(scope = {}),这就是为什么$ parent。$ parent.MyName = Tamilnadu(Angular 1.3更新的一部分)
发生的事情的一些细节: How to access parent scope from within a custom directive *with own scope* in AngularJS?
transclude:true - 该指令创建一个新的“transcluded”子节点 范围,原型继承自父范围。如果 指令还创建了一个隔离范围,transcluded和 隔离范围是兄弟姐妹。每个范围的$ parent属性 引用相同的父范围。
Angular v1.3更新:如果该指令还创建了隔离范围, 被抄送的范围现在是孤立范围的子代。该 被抄袭和孤立的范围不再是兄弟姐妹。 $ parent 现在,transcluded范围的属性引用了隔离范围。
Matthew的回答对于父子指令通信也是正确的。
答案 1 :(得分:15)
这对你有用吗?改编自this answer。
没有一种简单的方法可以访问被转换内容的父元素,因此我们将父控制器注入子节点以访问其范围。
var app = angular.module('myApp', []);
app.controller("CountryCtrl",function($scope){
$scope.myName = "India";
});
app.controller("StateCtrl",function($scope){
});
app.directive("state",function(){return {
restrict : 'E',
transclude: true,
scope : { myName : '=nameofthestate'},
template:"** {{myName}} is inside {{$parent.myName}}<br/><ng-transclude></ng-transclude>",
controller: function ($scope) {
this.getName = function () {
return $scope.myName;
}
}
}});
app.directive("city",function(){return {
restrict : 'E',
require:'^state',
scope : { myName : '=nameofthecity'},
template:"**** {{myName}} is inside {{parentName}} which is in {{$parent.myName }}<br/> ",
link: function(scope, element, attrs, ctrl) {
scope.parentName = ctrl.getName();
}
}});
答案 2 :(得分:2)
当AngularJS遇到transclude时,它会先克隆HTML 用模板或templateUrl内容替换它。然后,当它 遇到ng-transclude,它会编译被抄送的内容,但是 将它链接到父范围而不是孤立的范围 指示。因此,被抄送的内容仍然可以访问 父控制器及其内容,而指令HTML有一个 隔离范围(或新范围,视情况而定)。
AngularJS启动并运行
答案 3 :(得分:1)
检查我的指令的解决方案,它适用于许多公民。我做的是删除transclude并要求params。不要打扰脏HTML,只是看js,简单如f ..:D
CRM.directive('inputwv', function ($compile) {
var getTemplate = function(contentType) {
var template = '';
switch(contentType) {
case '3':
template = '<input type="number" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px;width:100px">'
break;
case '0':
template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">'
break;
case '1':
template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">'
break;
case '2':
template = '<textarea class="materialize-textarea teal-text" type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">'
break;
case '4':
template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">'
break;
case '5':
template = '<input type="date" class="datepicker" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px"><script type="text/javascript">$(\'.datepicker\').pickadate({selectMonths: true, selectYears: 15});</script>'
break;
default:
template = '<textarea class="materialize-textarea teal-text" type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index )" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">'
}
return template;
}
var linker = function(scope, element, attrs) {
element.html(getTemplate(attrs.typ)).show();
$compile(element.contents())(scope);
}
return {
restrict: "E",
link: linker
};
});