rlc*_*ews 9 javascript angularjs angularjs-directive
我有一个treeview指令归功于http://codepen.io/bachly/pen/KwWrzG 作为我的起始块.当我向集合中添加对象时,我正在尝试更新.我可以更新对象并插入新对象,但是一旦$scoped项目更新,就不会调用treeview指令.最终,所使用的数据将来自服务,此时我只是使用模拟数据进行测试.
原始集合看起来像这样
$scope.myList = {
children: [
{
name: "Event",
children: [
{
name: "Event Date",
parent:"Event",
children: [
{
name: "2008",
filterType: '_eventStartDate',
parent: 'Event'
},
{
name: "2009",
filterType: '_eventStartDate',
parent: 'Event'
}
]
},
{
name: "Event Attendee",
parent: "Event",
children: [
{
name: "Person 1",
filterType: '_eventAttenddeeName',
parent: 'Event Attendee'
},
{
name: "Person 2",
filterType: '_eventAttenddeeName',
parent: 'Event Attendee'
}
]
}
]
}]
};
var TheOtherCollection = {
children: [
{
name: "A New Event",
children: [
{
name: "The Other Date",
parent: " A New Event",
children: [
{
name: "2010",
FilterType: '_eventStartDate',
Parent: '_event'
},
{
name: "2011",
FilterType: '_eventStartDate',
Parent: '_event'
}
]
}
]
}]
};
Run Code Online (Sandbox Code Playgroud)
这将使用以下指令和html生成带有复选框的树视图
app.directive('tree', function () {
return {
restrict: 'E',
replace: true,
scope: {
t: '=src',
filter: '&'
},
controller: 'treeController',
template: '<ul><branch ng-repeat="c in t.children track by $index" src="c" filter="doSomething(object, isSelected)"></branch></ul>'
};
});
app.directive('branch', function($compile) {
return {
restrict: 'E',
replace: true,
scope: {
b: '=src',
filter: '&',
checked: '=ngModel'
},
template: '<li><input type="checkbox" ng-click="innerCall()" ng-model="b.$$hashKey" ng-change="stateChanged(b.$$hashKey)" ng-hide="visible" /><a>{{ b.name }}</a></li>',
link: function (scope, element, attrs) {
var clicked = '';
var hasChildren = angular.isArray(scope.b.children);
scope.visible = hasChildren;
if (hasChildren) {
element.append('<tree src="b"></tree>');
$compile(element.contents())(scope);
}
element.on('click', function(event) {
event.stopPropagation();
if (hasChildren) {
element.toggleClass('collapsed');
}
});
scope.stateChanged = function(b) {
clicked = b;
};
scope.innerCall = function() {
scope.filter({ object: scope.b, isSelected: clicked });
};
}
};
});
Run Code Online (Sandbox Code Playgroud)
然后是html
<div ng-controller="treeController">
<tree src="myList" iobj="object" filter="doSomething(object, isSelected)"></tree>
<a ng-click="clicked()"> link</a>
</div>
Run Code Online (Sandbox Code Playgroud)
单击复选框时,将使用lodashjs将新集合添加到现有集合中
ng-click事件
$scope.doSomething = function (object, isSelected) {
if (isSelected) {
var item = object;
console.log(item);
nestAssociation(object, $scope.myList, TheOtherCollection);
}
}
Run Code Online (Sandbox Code Playgroud)
它创建新数组并将其添加到children数组中
function nestAssociation(node, oldCollection, newAggregates) {
// var item = fn(oldCollection, node.parent);
var updatedArray = _.concat(oldCollection.children, newAggregates);
console.log(updatedArray);
if (updatedArray != null)
updateMyList(updatedArray);
}
Run Code Online (Sandbox Code Playgroud)
我可以在输出中看到我有一个新对象,但我无法更新treeview.我已经在指令中尝试在指令中的click事件上添加$ compile(元素),但由于数组没有构建,所以没有任何改变.
我是否需要在此指令中添加$ watch,如果是,还是有其他方法可以让指令重新呈现并显示新的嵌套集合吗?
更新
根据一些反馈和问题,这里有一个关于这个问题的更多细节.我所看到的问题不在指令中,只要围绕问题移动数据,一旦将数组添加到现有模型,我就无法重新渲染树视图.以下链接是一个工作的plunker,它显示了当前工作的项目.运行chrome dev工具我可以在输出中看到模型在选中复选框后更新

当我看到对象被更新时,指令永远不会更新以显示添加到对象的新数组.这是我需要帮助理解的部分.
提前致谢
您将函数传递给内部指令(这是最佳实践),但您可以访问scope.filter. 不是doSomethingFunction。这个就undefined在那里。
filter="doSomething(object, isSelected)"
=>
filter="filter(object, isSelected)"
app.directive('tree', function () {
return {
restrict: 'E',
replace: true,
scope: {
t: '=src',
filter: '&'
},
controller: 'treeController',
template: '<ul>
<branch ng-repeat="c in t.children track by $index"
src="c" filter="filter(object, isSelected)">
</branch>
</ul>'
};
});
Run Code Online (Sandbox Code Playgroud)
下一个 :
你永远无法访问$$AngularJS 中的变量,因为它们是私有的。也许你应该从你的数据库中制作一个......,但这$$hashkey似乎是一个简单的解决方案。
checked属性可能会引发错误,因为ngModel在您的树指令模板上不存在。(至少?在前面放一个)
复选框不能将 $$hashkey 作为模型。
ng-change 和 ng-click 总是会同时被调用,使用最简单的一个。
app.directive('branch', function($compile) {
return {
restrict: 'E',
replace: true,
scope: {
b: '=src',
filter: '&'
},
template: '<li><input type="checkbox" ng-click="innerCall(b.$$hashKey)" ng-model="isChecked" ng-hide="visible" /><a>{{ b.name }}</a></li>',
link: function (scope, element, attrs) {
scope.isChecked = false;
var hasChildren = angular.isArray(scope.b.children);
scope.visible = hasChildren;
if (hasChildren) {
element.append('<tree src="b"></tree>');
$compile(element.contents())(scope);
}
element.on('click', function(event) {
event.stopPropagation();
if (hasChildren) {
element.toggleClass('collapsed');
}
});
scope.innerCall = function(hash) {
if(scope.isChecked){
scope.filter({ object: scope.b, isSelected: hash });
}
};
}
};
});
Run Code Online (Sandbox Code Playgroud)
更新
treeController您的tree指令和观点也是如此index.html。
这就是导致视图不更新的原因!
我删除了你的指令中的那个,否则你将为每个孩子都有一个控制器。
您在控制器中看到了良好的 console.log 消息,但它是在 ONE 指令的控制器中。
您没有访问 的控制器index.html。
然后我修复了filter孩子之间的功能通信:
当您附加 new 时,您忘记传达过滤器功能tree:
element.append('<tree src="b" filter="filter({ object: object, isSelected: isSelected })"></tree>');
此外,在父指令模板中,您还需要哈希将参数发送到函数:
filter="filter({ object: object, isSelected: isSelected })"
我在这里编辑了你的 Plunker ,没有使用我所做的上述评论更改代码。
(我不确定你写的不是你想要的,因为你没有评论,我宁愿不改变它,所以你仍然可以快速理解你的代码)
但是视图现在正在更新!
我认为根据您想要的内容进行一些调试,上面的评论应该足够了。
编辑2
您忘记返回具有属性的对象chrilden。您返回了一个数组,这导致了问题。
function updateMyList(data) {
var transformed = { children : data };
$scope.myList = transformed;
}
Run Code Online (Sandbox Code Playgroud)
这是一个正在工作的PLUNKER。
| 归档时间: |
|
| 查看次数: |
1186 次 |
| 最近记录: |