Нокаут, связывающий отношения "один ко многим" с самим собой (рекурсия в нокауте)

Поэтому в моей базе данных есть модель, которая имеет отношение один ко многим с самим собой. Хорошим примером этого является система комментариев, как на reddit.

В настоящее время я делаю что-то вроде этого:

<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>

который, очевидно, поддерживает только один уровень детей. Есть ли чистый способ структурировать это, когда Child (Children[i]) может или не может иметь массив 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":[  
                  {  
                     "@odata.context":"http://localhost:3080/odata/$metadata#SectionApi(*)/$entity",
                     "SectionID":4,
                     "Text":"Text",
                     "Html":null,
                     "OrderQualifier":"1",
                     "IsUserCreated":false,
                     "Children":[  

                     ]
                  }
               ]
            }
         ]
      }
   ]
}

Как вы можете видеть, он содержит 3 уровня дочерних комментариев, но мне нужно иметь возможность обрабатывать неизвестное количество дочерних комментариев.

2 ответа

Решение

Шаблон нокаута поддерживает рекурсию. 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>

Вы можете использовать шаблон для этого

<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>

образец 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())
})

Скрипка Демо

Другие вопросы по тегам