@reactreact

Как в meteor правильно вывести все данные из базы в таблицу?

{
"_id" : "kCwbRfsi9wLTwciGL",
"title" : "Test"
},
{
"_id" : "2RxhjiuBA5Nf7KtWu",
"title" : "Test1"
},
{
"_id" : "78gGbshheCsDPoWZk",
"title" : "Test2"
},
{
"_id" : "sMkY3QnAmg3uxtXkq",
"title" : "Child",
"parentId" : "2RxhjiuBA5Nf7KtWu"
 },
 {
"_id" : "wMkf5QnAmg3nutMkq",
"title" : "Child1",
"parentId" : "2RxhjiuBA5Nf7KtWu"
 }


Нужно вывести на страницу, чтобы получилась такая структура:
<ol>
<li><div>Test</div></li>
<li><div>Test1</div>
 <ol>
<li><div>Child</div></li>
<li><div>Child1</div></li>
</ol>
</li>
<li><div>Test2</div></li>
</ol>


Причём я не знаю сколько может быть вложенных элементов. Как правильно так вывести?
  • Вопрос задан
  • 152 просмотра
Пригласить эксперта
Ответы на вопрос 1
evilandfox
@evilandfox
Javascript, meteor, Qt
Интересная задачка) Жаль пораньше не увидел.
Можно ее решить, используя встроенную в Meteor библиотеку Underscore и рекурсию :).
Пусть имеются такие тестовые данные:

const _id1 = Items.insert({title: 'Item 1'});
const _id2 = Items.insert({title: 'Item 2'});
  const _id21 = Items.insert({title: 'Item 2.1', parent: _id2});
  const _id22 = Items.insert({title: 'Item 2.2', parent: _id2});
    const _id221 = Items.insert({title: 'Item 2.2.1', parent: _id22});
    const _id222 = Items.insert({title: 'Item 2.2.1', parent: _id22});
  const _id23 = Items.insert({title: 'Item 2.3', parent: _id2});
const _id3 = Items.insert({title: 'Item 3'});
  const _id31 = Items.insert({title: 'Item 3.1', parent: _id3});
const _id4 = Items.insert({title: 'Item 4'});
const _id5 = Items.insert({title: 'Item 5'});


Получаем их

var items = Items.find().fetch();

Теперь представляем эти данные в виде дерева. Каждый лист дерева - объект со значением title и потомками children. Строим такое дерево через следующую функцию:

function getAsTree(items) {
  // для корневых элементов ставим _id родителя пустой строкой ''
  var extItems = _.map(items, function(item){
    if ('parent' in item)
      return item;
    else
      return _.extend(item, {parent: ''});
  });
  // данная функция рекурсивно возвращает потомков элемента с заданным _id,
  // которые в свою очередь также содержат потомков и т.д.
  // если же потомка у элемента нет, то в нем {children: []}
  function recBuildTree(_id){
    var result = [];
    return _.map(_.filter(extItems, function(item){
      return item.parent === _id;
    }), function(item){
      return _.extend(item, {
        children: recBuildTree(item._id)
      });
    });
  }
  // определяем корень дерева, который не содержит значения,
  // а его потомки - корневые элементы с {parent: ''}
  var tree = {
    title: '',
    _id: '',
    children: recBuildTree('')
  };
  return tree;
}


Теперь создадим темплейт, использующий вспомогательный для отрисовки, затем выведем в нем сгенерированное дерево:

Template.listView.helpers({
  children: function(){
    return getAsTree(Items.find().fetch()).children;
  }
});

<template name="listView">
  <ol>
    {{#each children}}
      {{> _listViewItem}}
    {{/each}}
  </ol>
</template>

<template name="_listViewItem">
<li>
  <div>{{title}}</div>
  {{#if children}}
    <ol>
      {{#each children}}
        {{> _listViewItem}}
      {{/each}}
    </ol>
  {{/if}}
</li>
</template>


Результат:

ad8001bb04874b2d8e58e2043b1f8fa4.png

Стоит заметить, что некорневые элементы с несуществующим родителем не будут включены в дерево.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы