我有一个treeview指令,我试图从父控制器调用一个函数,我似乎无法得到函数来调用。我不确定是否是由于树视图的结构和子元素的嵌套或者是什么。
在我的html中,我将指令声明为:
<div ng-controller="treeController as vm">
<tree src="myList" filter="doSomething()"></tree>
<a ng-click="clicked()"> link</a>
</div>
我在指令中声明了一个属性/参数filter
,它应该调用主控制器中的doSomething()
函数。
主控制器包含以下代码(用于构建树以及调用函数的测试。
app.controller("treeController", ['$scope', function($scope) {
var vm = this;
$scope.doSomething = function () {
var item = data;
}
$scope.clicked = function () {
alert('clicked');
}
$scope.myList = {
children: [
{
name: "Event",
children: [
{
name: "Event Date",
children: [
{
name: "2008",
FilterType: '_eventStartDate',
Parent: '_event'
},
{
name: "2009",
FilterType: '_eventStartDate',
Parent: '_event'
}
]
},
{
name: "Event Attendee",
children: [
{
name: "Person 1",
FilterType: '_eventAttenddeeName',
Parent: '_Event'
},
{
name: "Person 2",
FilterType: '_eventAttenddeeName',
Parent: '_Event'
}
]
}
]
}]
};
}]);
在我的指令中,我声明了隔离范围,以及参数filter
(第二个app.directive),我使用模型绑定前缀'&'
作为前缀。在模板中,我然后调用ng-click,它应该调用主控制器中的函数doSomething()。但是......没有骰子。
app.directive('tree', function() {
//builds the tree
return {
restrict: 'E',
replace: true,
scope: {
t: '=src'
},
template: '<ul><branch ng-repeat="c in t.children" src="c"></branch></ul>'
};
});
app.directive('branch', function($compile) {
//directive that builds the children/branches
return {
restrict: 'E',
replace: true,
scope: {
b: '=src',
filter: '&'
},
template: '<li><input type="checkbox" ng-click="filter()" ng-hide="visible" /><a>{{ b.name }}</a></li>',
link: function (scope, element, attrs) {
var has_children = angular.isArray(scope.b.children);
scope.visible = has_children;
if (has_children) {
element.append('<tree src="b"></tree>');
$compile(element.contents())(scope);
}
element.on('click', function(event) {
event.stopPropagation();
if (has_children) {
element.toggleClass('collapsed');
}
});
//test to call function within directive
//scope.doSomething = function(b) {
// alert('test');
//}
}
};
});
我发布了公开jsFiddle以及工作代码示例
对我错过的任何建议?
现在我只是试图调用该方法,但最终我需要将所选项目作为参数传递回控制器,但是现在我只想弄清楚为什么我的控制器中的函数会不被打电话。
提前致谢
更新 有人建议将过滤器的声明从分支移动到树指令。
我在本地更新了代码,因此树指令如下所示:
app.directive('tree', function() {
return {
restrict: 'E',
replace: true,
scope: {
t: '=src',
filter: '&'
},
template: '<ul><branch ng-repeat="c in t.children" src="c"></branch></ul>'
};
});
注意:filter参数已从辅助指令中删除。输出没有变化。控制器内的功能仍未调用。
答案 0 :(得分:0)
你的树指令没有filter方法。你的branch指令只有那个属性
<div ng-controller="treeController as vm">
<tree src="myList" filter="doSomething()"></tree>
<a ng-click="clicked()"> link</a>
</div>
app.directive('tree', function() {
//builds the tree
return {
restrict: 'E',
replace: true,
scope: {
t: '=src',
filter: '&'
},
template: '<ul><branch ng-repeat="c in t.children" src="c" filter="doSomething()"></branch></ul>'
};
});
app.directive('branch', function($compile) {
//directive that builds the children/branches
return {
restrict: 'E',
replace: true,
scope: {
b: '=src',
filter: '&'
},
template: '<li><input type="checkbox" ng-click="filter()" ng-hide="visible" /><a>{{ b.name }}</a></li>',
link: function (scope, element, attrs) {
var has_children = angular.isArray(scope.b.children);
scope.visible = has_children;
if (has_children) {
element.append('<tree src="b"></tree>');
$compile(element.contents())(scope);
}
element.on('click', function(event) {
event.stopPropagation();
if (has_children) {
element.toggleClass('collapsed');
}
});
//test to call function within directive
//scope.doSomething = function(b) {
// alert('test');
//}
}
};
});
答案 1 :(得分:0)
<强>更新强> Sundar的评论让我走上正确的道路这里是更新的指令,对我来说主要的问题是我正在使用嵌套指令,因此嵌套项(正在进行函数调用)超出了控制器的范围更正这包括Sundar的更改,但要使嵌套指令起作用,我必须在父指令级别显式设置控制器。如果您需要在应用程序的多个区域中使用指令,我意识到这不是一个好的选择。但对我来说,该指令仅用于一个位置,因此该解决方案有效。如果有人有任何其他建议或更好的方法,我会感激他们。
app.directive('tree', function() {
return {
restrict: 'E',
replace: true,
scope: {
t: '=src',
filter: '&'
},
controller:'treeController', //explicitly set the controller of the parent directive
template: '<ul><branch ng-repeat="c in t.children" src="c" filter="doSomething(data)"></branch></ul>'
};
});
app.directive('branch', function($compile) {
return {
restrict: 'E',
replace: true,
scope: {
b: '=src',
filter: '&'
},
template: '<li><input type="checkbox" ng-click="innerCall()" ng-hide="visible" /><a>{{ b.name }}</a></li>',
link: function (scope, element, attrs) {
var has_children = angular.isArray(scope.b.children);
scope.visible = has_children;
if (has_children) {
element.append('<tree src="b"></tree>');
$compile(element.contents())(scope);
}
element.on('click', function(event) {
event.stopPropagation();
if (has_children) {
element.toggleClass('collapsed');
}
});
scope.innerCall = function() {
scope.filter(scope.b);
}
}
};
});