问题
So in my database I have a model that has a one to many relationship with itself. A good example of this is a comments system like on reddit.
I currently am doing something like this:
<div class="body" data-bind="foreach: { data: Comments}">
<span data-bind="text: '(' + OrderQualifier + ') ' + Text"></span>
<!-- ko foreach: { data: Children } -->
<span data-bind="text: '(' + OrderQualifier + ') ' + Text"></span>
<!-- /ko -->
</div>
which obviously only supports one level of children. Is there a clean way to structure this when a Child (Children[i]) may or may not also have a Children array that needs to be looped over. In my example there could technically be infinite levels like this (it won't be).
I'm pretty sure I could come up with something hacky but I think there may be a better way. Thanks.
Edit:
Data that I would want to map:
{
"@odata.context":"http://localhost:3080/odata/$metadata#SectionApi(*)/$entity",
"SectionID":4,
"Text":"Text",
"Html":null,
"OrderQualifier":"1",
"IsUserCreated":false,
"Children":[
{
"@odata.context":"http://localhost:3080/odata/$metadata#SectionApi(*)/$entity",
"SectionID":4,
"Text":"Text",
"Html":null,
"OrderQualifier":"1",
"IsUserCreated":false,
"Children":[
{
"@odata.context":"http://localhost:3080/odata/$metadata#SectionApi(*)/$entity",
"SectionID":4,
"Text":"Text",
"Html":null,
"OrderQualifier":"1",
"IsUserCreated":false,
"Children":[
{
"@odata.context":"http://localhost:3080/odata/$metadata#SectionApi(*)/$entity",
"SectionID":4,
"Text":"Text",
"Html":null,
"OrderQualifier":"1",
"IsUserCreated":false,
"Children":[
]
}
]
}
]
}
]
}
As you can see this contains 3 levels of child comment but I need to be able to handle an unknown number of child comments.
回答1:
knockout template supports recursion. http://jsfiddle.net/m812qjeq/2/
<div class="body" data-bind="foreach: Comments">
<div data-bind="template: { name: 'childTemplate', data: $data }"></div>
</div>
<script type="text/html" id="childTemplate">
<span data-bind="text: '(' + OrderQualifier + ') ' + Text"></span>
<!-- ko if: $data.Children -->
<!-- ko foreach: Children -->
<div data-bind="template: { name: 'childTemplate', data: $data }"></div>
<!-- /ko -->
<!-- /ko -->
</script>
回答2:
You can use template for this
<div class="body" data-bind="foreach: comments">
<div data-bind="template: { name: 'childTemplate', data: $data }"></div>
</div>
<script type="text/html" id="childTemplate">
<span data-bind="text:comment"></span>
<!-- ko if: $data.childrenLength > 0 -->
<!-- ko foreach: children -->
<div data-bind="template: { name: 'childTemplate', data: $data }" style="padding-left:35px;"></div>
<!-- /ko -->
<!-- /ko -->
</script>
sample Viewmodel
var comments = [{
id: 1,
comment: 'How can i use knockoutjs?',
childrenLength: 3,
children: [{
id: 2,
comment: 'Please seach before asking',
childrenLength: 0,
children: []
}, {
id: 3,
comment: 'Please read the documentation',
childrenLength: 0,
children: []
}, {
id: 4,
comment: 'You can see the blog posts on this',
childrenLength: 2,
children: [{
id: 5,
comment: 'Please seach before asking',
childrenLength: 0,
children: []
}, {
id: 6,
comment: 'Please seach before asking',
childrenLength: 0,
children: []
}]
}]
}, {
id: 7,
comment: 'You question is not sufficient to be asked here?',
childrenLength: 3,
children: [{
id: 8,
comment: 'Please seach before asking',
childrenLength: 0,
children: []
}, {
id: 9,
comment: 'Please read the documentation',
childrenLength: 0,
children: []
}, {
id: 10,
comment: 'You can see the blog posts on this',
childrenLength: 0,
children: []
}]
}]
var vm = function(){
var self = this
self.comments = ko.observableArray(comments)
}
$('document').ready(function () {
ko.applyBindings(new vm())
})
Fiddle Demo
来源:https://stackoverflow.com/questions/25217649/knockout-binding-a-one-to-many-relationship-on-self-recursion-in-knockout