@KhalBay

Как в select положить все значения включая вложенные из массива объектов?

Есть список пользователей (массив из объектов). Объекты могут до бесконечности вложены друг в друга.
62d5390f930c8686011830.png
Я сделал рекурсивный компонент который выводит этот список:
62d539768e08c177777278.png
Сейчас мне нужно добавлять нового пользователя с возможностью выбора родителя, через тег SELECT.
Как мне получить список всех пользователей в селект, сейчас получаю только тех кто на самом верхнем уровне.
Сделать option рекурсией не выходит. Я могу просто собрать всех через querySelectorAll, но думаю это не самое лучшее решение и как потом добавлять нового пользователя в конкретного родителя, тоже не могу догадаться.

Вот компонент селект

<template>
  <select
    v-bind:value="user.head"
    @input="user.head = $event.target.value"
  >
    <option value=""></option>
    <option v-for="user in elements" :key="user">{{user.name}}</option>
  </select>
</template>

<script>
export default {
  props: {
    elements: {
      type: Array,
      required: true
    }
  },
  data() {
    return {
      user: {
        name: '',
        tel: '',
        head: '',
      }
    }
  }
}
</script>


Вот так реализована рекурсия для вывода списка:

Родительский компонент
<template>
  <div class="table">
    <div class="element">
      <div class="wrap">
        <div class="table-name">Имя</div>
        <div class="table-tel">Телефон</div>
      </div>
    </div>
    <User
      class="element"
      v-for="user in elements"
      :key="user.id"
      :id="user.id"
      :user="user"
    >
    </User>
  </div>
</template>

<script>
import User from "./User";
export default {
  components: {User},
  props: {
    elements: {
      type: Array,
      required: true
    }
  },
  methods: {}
}
</script>

Компонент юзер

<template>
  <div>
    <div class="wrap">
      <div class="element-name">{{ user.name }}</div>
      <div class="element-tel">{{ user.tel }}</div>
    </div>
    <User
      class="child"
      v-for="child in user.children"
      v-bind:user="child"
      :key="child.id"
      :parentItem="user"
    />
  </div>
</template>

<script>
export default {
  name: 'User',
  props: {
    user: {
      type: Object,
      required: true
    },
    parentItem: {
      required: false
    }
  }
}
</script>

  • Вопрос задан
  • 423 просмотра
Решения вопроса 1
0xD34F
@0xD34F Куратор тега Vue.js
Понадобится функция, которая вложенный массив развернёт в плоский:

const flat = (arr, childrenKey = 'children') =>
  (arr instanceof Array ? arr : []).reduce((acc, n) => (
    acc.push(n, ...flat(n[childrenKey], childrenKey)),
    acc
  ), []);

// или, если нужны копии объектов без ссылок на массивы вложенных объектов:
const flat = (arr, childrenKey = 'children') =>
  Array.isArray(arr)
    ? arr.flatMap(({ [childrenKey]: c, ...n }) => [
        n,
        ...flat(c, childrenKey),
      ])
    : [];

Дальше всё просто - вычисляемое свойство, v-for по его значению:

computed: {
  users() {
    return flat(this.elements);
  },
},

<option v-for="n in users" :key="n.id">{{ n.name }}</option>
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
SilenceOfWinter
@SilenceOfWinter
та еще зажигалка...
Сделать option рекурсией не выходит.
почему? или ты пытаешься их вкладывать друг в друга? если так то, select поддерживает только 1 ур вложенности т.ч. либо делай вложенные dropdown меню мимикрирующие под select(ы) и сохраняй значение в input'е, либо используй стандартный select,а уровень вложенности отображай отступом в option'аx:
<option value="1">1пункт 1ур</option>
<option value="2">- 1пункт  2ур</option>
<option value="2">- 2пункт 2ур</option>
<option value="2">- - 1пункт 3ур</option>
<option value="2">2пункт 1ур</option>
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы