Skip to content

useFieldArray ​

Список полей: позиции заказа, телефоны, участники. Даёт устойчивые ключи для v-for и операции над строками. При удалении и перестановке отметки «тронуто» переезжают вместе со строками — ошибка не перескочит на соседнюю строку.

Сигнатура ​

ts
function useFieldArray<T>(path: string): FieldArray<T>
function useFieldArray<T>(form: Form, path: string): FieldArray<T>
ВозвращаетОписание
fields{ key, index, path, value }[] — key для v-for, path для ошибок и touch
append(value), prepend(value)Добавить строку в конец / в начало
insert(index, value)Вставить строку
remove(index)Удалить строку
move(from, to), swap(a, b)Переставить строки
replace(values)Заменить весь список

Без form форма берётся из контекста. Если массива в values нет, он будет создан. Прямые изменения (form.values.items.push(...)) тоже работают — новые строки получат ключи.

Пример ​

vue
<script setup lang="ts">
const Order = object({
  items: pipe(array(object({ title: pipe(string(), minLength(2)), qty: pipe(coerce.number(), min(1)) })), minLength(1)),
});

const form = useForm(Order, { initial: { items: [{ title: '', qty: '1' }] } });
const items = useFieldArray<{ title: string; qty: string }>(form, 'items');
</script>

<template>
  <div v-for="field in items.fields.value" :key="field.key">
    <input v-model="field.value.title" :name="`${field.path}.title`" @blur="form.touch(`${field.path}.title`)" />
    <span>{{ form.errors[`${field.path}.title`] }}</span>

    <input v-model="field.value.qty" :name="`${field.path}.qty`" @blur="form.touch(`${field.path}.qty`)" />

    <button type="button" :disabled="field.index === 0" @click="items.move(field.index, field.index - 1)">↑</button>
    <button type="button" @click="items.remove(field.index)">×</button>
  </div>
  <button type="button" @click="items.append({ title: '', qty: '1' })">+</button>
</template>

Почему не индекс в :key: при удалении первой строки все индексы сдвигаются, и Vue переиспользует поля не тех строк — фокус и введённый текст «перепрыгивают».

См. также ​