Vuetify предоставляет мощный набор компонентов для создания форм, которые могут адаптироваться под данные и условия приложения. Динамические формы — это формы, структура которых формируется на основе данных, состояния приложения или пользовательских действий. Такой подход позволяет создавать гибкие интерфейсы, где поля и их свойства (тип, валидация, доступность) могут изменяться без ручного редактирования шаблона.
В Vuetify для динамических форм часто используют сочетание v-for, v-model, реактивных данных и вычисляемых свойств. Основной принцип: структура формы хранится в виде массива объектов, где каждый объект описывает поле: тип, метку, модель данных и правила валидации.
Пример структуры данных для формы:
data() {
return {
formFields: [
{ type: 'text', label: 'Имя', model: 'name', rules: [(v) => !!v || 'Поле обязательно'] },
{ type: 'email', label: 'Email', model: 'email', rules: [(v) => /.+@.+\..+/.test(v) || 'Некорректный email'] },
{ type: 'select', label: 'Страна', model: 'country', items: ['Россия', 'США', 'Германия'], rules: [(v) => !!v || 'Выберите страну'] }
],
formData: {
name: '',
email: '',
country: null
}
}
}
Каждое поле формы описывается объектом с ключами:
text,
email, select, checkbox,
radio, textarea и др.).formData,
связанный с v-model.Для динамического создания формы используется v-for:
<v-form ref="form" v-model="valid">
<v-container>
<v-row>
<v-col
v-for="field in formFields"
:key="field.model"
cols="12"
md="6"
>
<component
:is="getComponent(field.type)"
v-model="formData[field.model]"
:label="field.label"
:rules="field.rules"
:items="field.items"
></component>
</v-col>
</v-row>
<v-btn @click="submitForm" :disabled="!valid">Отправить</v-btn>
</v-container>
</v-form>
Метод getComponent возвращает конкретный компонент Vuetify в зависимости от типа:
methods: {
getComponent(type) {
switch(type) {
case 'text': return 'v-text-field';
case 'email': return 'v-text-field';
case 'select': return 'v-select';
case 'textarea': return 'v-textarea';
case 'checkbox': return 'v-checkbox';
default: return 'v-text-field';
}
},
submitForm() {
if (this.$refs.form.validate()) {
console.log('Данные формы:', this.formData);
}
}
}
Динамические формы часто требуют условного отображения полей. Vuetify поддерживает это через v-if и вычисляемые свойства.
Пример: поле “Регион” отображается только если выбрана определённая страна:
computed: {
visibleFields() {
return this.formFields.filter(field => {
if (field.model === 'region') {
return this.formData.country === 'Россия';
}
return true;
});
}
}
<v-col
v-for="field in visibleFields"
:key="field.model"
cols="12"
md="6"
>
<component
:is="getComponent(field.type)"
v-model="formData[field.model]"
:label="field.label"
:rules="field.rules"
:items="field.items"
></component>
</v-col>
Для форм с возможностью добавления нескольких одинаковых блоков
используют массивы объектов в formData.
Пример: добавление нескольких контактов:
data() {
return {
contacts: [
{ name: '', phone: '' }
]
}
},
methods: {
addContact() {
this.contacts.push({ name: '', phone: '' });
},
removeContact(index) {
this.contacts.splice(index, 1);
}
}
<v-row v-for="(contact, index) in contacts" :key="index">
<v-col cols="6">
<v-text-field v-model="contact.name" label="Имя"></v-text-field>
</v-col>
<v-col cols="6">
<v-text-field v-model="contact.phone" label="Телефон"></v-text-field>
</v-col>
<v-col cols="12">
<v-btn @click="removeContact(index)">Удалить</v-btn>
</v-col>
</v-row>
<v-btn @click="addContact">Добавить контакт</v-btn>
Динамические формы часто строятся на основе данных с сервера, например JSON-описания полей:
mounted() {
axios.get('/api/form-fields').then(response => {
this.formFields = response.data.fields;
response.data.fields.forEach(field => {
this.$set(this.formData, field.model, field.default || '');
});
});
}
Такой подход позволяет изменять структуру формы без изменения шаблона, что особенно удобно для многостраничных или настраиваемых форм.
formData.Динамические формы в Vuetify дают возможность строить гибкие и масштабируемые интерфейсы, полностью управляемые через данные и реактивное состояние приложения.