Документация библиотеки CRUD Dialogs
Библиотека для создания модальных диалоговых окон на основе Bootstrap с поддержкой CRUD операций, вкладок и гибкой настройкой макета.
Оглавление
- Подключение
- Основные концепции
- API Reference
- Типы полей
- Настройки диалога
- Layout и категории
- Примеры использования
Подключение
<!-- Зависимости -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<!-- Библиотека dom.js (должна быть подключена первой) -->
<script src="dom.js"></script>
<!-- Библиотека CRUD Dialogs -->
<script src="crud_d.js"></script>
Основные концепции
Библиотека работает с тремя основными режимами открытия диалога:
- create — создание нового элемента (пустая форма)
- update — редактирование существующего элемента (форма с подгруженными данными)
- create from — создание нового элемента из существующего (форма с подгруженными данными)
Каждый диалог имеет:
- Уникальный строковый идентификатор (dialogId)
- Набор полей с типами и настройками
- Эндпоинты для CRUD операций (устанавливаются отдельно)
- Опциональные настройки отображения (ширина, категории)
Управлять диалогом можно:
- Через объект, полученный при создании
- Через глобальные методы, используя dialogId
API Reference
makeDialog
Создает новый диалог и возвращает объект для работы с ним.
crud_d.makeDialog(dialogId, fields, options)
Параметры:
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
| dialogId | string | Да | Уникальный идентификатор диалога (не DOM id) |
| fields | object | Да | Объект с описанием полей |
| options | object | Нет | Дополнительные настройки диалога |
Возвращает: Объект диалога с методами управления.
Пример:
const dialog = crud_d.makeDialog('user_form', {
name: ['text', { label: 'Имя', required: true }, ''],
email: ['email', { label: 'Email', required: true }, '']
}, {
width: 'lg'
});
Методы объекта диалога
setCreateEndpoint(endpoint)
Устанавливает endpoint для создания элемента (POST).
dialog.setCreateEndpoint('/api/users')
setUpdateEndpoint(endpoint)
Устанавливает endpoint для обновления элемента (PUT). Используйте {id} для подстановки ID элемента.
dialog.setUpdateEndpoint('/api/users/{id}')
setGetEndpoint(endpoint)
Устанавливает endpoint для получения данных элемента (GET). Используйте {id} для подстановки ID элемента.
dialog.setGetEndpoint('/api/users/{id}')
setDeleteEndpoint(endpoint)
Устанавливает endpoint для удаления элемента (DELETE). Используйте {id} для подстановки ID элемента.
dialog.setDeleteEndpoint('/api/users/{id}')
openCreate(title)
Открывает диалог в режиме создания.
dialog.openCreate('Новый пользователь')
.onSuccess(function(result) {
console.log('Создан:', result);
})
.onError(function(error) {
console.error('Ошибка:', error);
});
openUpdate(itemId, title)
Открывает диалог в режиме редактирования. Автоматически загружает данные через GET endpoint.
dialog.openUpdate(42, 'Редактирование пользователя')
.onSuccess(function(result) {
console.log('Обновлен:', result);
})
.onDelete(function(id) {
console.log('Удален:', id);
})
.onError(function(error) {
console.error('Ошибка:', error);
});
openCreateFrom(itemId, title)
Открывает диалог в режиме создания с загруженными данными через GET endpoint.
dialog.openUpdate(42, 'Создание копии пользователя')
.onSuccess(function(result) {
console.log('Создана копия:', result);
})
.onError(function(error) {
console.error('Ошибка:', error);
});
getConfig()
Возвращает текущую конфигурацию диалога.
const config = dialog.getConfig();
console.log(config.fields, config.options, config.endpoints);
destroy()
Удаляет регистрацию диалога и закрывает его, если открыт.
dialog.destroy();
Методы API при открытом диалоге
При открытии диалога возвращается объект с методами для управления текущим экземпляром:
const api = dialog.openCreate('Заголовок');
onSuccess(callback)
Устанавливает обработчик успешного выполнения операции.
api.onSuccess(function(result) {
// result - данные, возвращенные сервером
console.log('Успех:', result);
});
onError(callback)
Устанавливает обработчик ошибок.
api.onError(function(error) {
console.error('Ошибка:', error.message);
});
onDelete(callback)
Устанавливает обработчик успешного удаления (только для режима update).
api.onDelete(function(itemId) {
console.log('Удален элемент с ID:', itemId);
});
onOpen(callback)
Устанавливает обработчик успешного открытия. Если диалог открыт в режиме редактирования, функция будет вызвана после загрузки всех данных.
api.onOpen(function() {
console.log('Диалог открыт и загружен');
});
setValues(values)
Устанавливает значения полей формы.
api.setValues({
name: 'Иван',
email: 'ivan@example.com'
});
getFormData()
Возвращает текущие данные формы.
const data = api.getFormData();
console.log(data);
close()
Закрывает диалог программно.
api.close();
show()
Показывает диалог (если был скрыт).
api.show();
Глобальные методы
Работа с диалогами через глобальный объект crud_d по dialogId.
setCreateEndpoint(dialogId, endpoint)
crud_d.setCreateEndpoint('user_form', '/api/users');
setUpdateEndpoint(dialogId, endpoint)
crud_d.setUpdateEndpoint('user_form', '/api/users/{id}');
setGetEndpoint(dialogId, endpoint)
crud_d.setGetEndpoint('user_form', '/api/users/{id}');
setDeleteEndpoint(dialogId, endpoint)
crud_d.setDeleteEndpoint('user_form', '/api/users/{id}');
openCreate(dialogId, title)
crud_d.openCreate('user_form', 'Новый пользователь')
.onSuccess(function(result) {
console.log('Создан:', result);
});
openUpdate(dialogId, itemId, title)
crud_d.openUpdate('user_form', 42, 'Редактирование')
.onSuccess(function(result) {
console.log('Обновлен:', result);
});
openCreateFrom(dialogId, itemId, title)
crud_d.openUpdate('user_form', 42, 'Копирование')
.onSuccess(function(result) {
console.log('Создан из объекта:', result);
});
closeDialog(dialogId)
crud_d.closeDialog('user_form');
getRegisteredDialogs()
const dialogs = crud_d.getRegisteredDialogs();
console.log(dialogs); // ['user_form', 'product_form']
closeAll()
crud_d.closeAll();
Типы полей
text
Текстовое поле ввода.
fieldName: ['text', {
label: 'Название поля', // string - заголовок
required: true, // boolean - обязательно для заполнения
placeholder: 'Подсказка', // string - текст-подсказка
readonly: false, // boolean - только для чтения
maxlength: 100 // number - максимальная длина
}, 'значение по умолчанию']
number
Числовое поле ввода.
fieldName: ['number', {
label: 'Цена',
required: true,
min: 0, // number - минимальное значение
max: 1000000, // number - максимальное значение
step: 0.01 // number - шаг изменения
}, 0]
Поле для email с валидацией формата.
fieldName: ['email', {
label: 'Email',
required: true,
placeholder: 'user@example.com'
}, '']
password
Поле для пароля (скрытый ввод).
fieldName: ['password', {
label: 'Пароль',
required: true,
placeholder: 'Введите пароль'
}, '']
textarea
Многострочное текстовое поле.
fieldName: ['textarea', {
label: 'Описание',
required: false,
rows: 5 // number - количество строк
}, '']
select
Выпадающий список.
fieldName: ['select', {
label: 'Категория',
required: true,
options: [ // array - список опций
{ value: 'electronics', label: 'Электроника' },
{ value: 'books', label: 'Книги' },
{ value: 'clothing', label: 'Одежда' }
]
}, 'electronics'] // значение по умолчанию
checkbox
Флажок (чекбокс).
fieldName: ['checkbox', {
label: 'Активен',
required: false
}, true] // значение по умолчанию
date
Поле выбора даты.
fieldName: ['date', {
label: 'Дата рождения',
required: true
}, '2024-01-01']
custom
Кастомное поле на основе HTMLElement.
const customElement = document.createElement('div');
customElement.innerHTML = `
<label class="form-label">Цвет</label>
<input type="color" class="form-control">
`;
fieldName: ['custom', customElement, '#ff0000']
Настройки диалога
Объект options передается третьим параметром в makeDialog:
{
width: 'lg', // Ширина диалога: 'sm', 'lg', 'xl' или CSS значение ('800px', '90%')
categories: { // Категории (вкладки)
'Основное': [
['name', 'price'],
['description']
],
'Дополнительно': [
['sku', 'weight'],
['dimensions']
]
}
}
Layout и категории
Без категорий
Если категории не указаны, все поля отображаются последовательно по одному в ряду.
crud_d.makeDialog('simple', {
name: ['text', { label: 'Имя' }, ''],
email: ['email', { label: 'Email' }, ''],
phone: ['text', { label: 'Телефон' }, '']
});
Layout в категориях
Каждая категория содержит массив рядов. Ряд — это массив имен полей, которые будут в одной строке.
categories: {
'Основная информация': [
['first_name', 'last_name'], // 2 поля в ряд
['email', 'phone'], // 2 поля в ряд
['address'] // 1 поле в ряд
],
'Дополнительно': [
['birth_date', 'gender'], // 2 поля в ряд
['notes'] // 1 поле в ряд
]
}
Автоматическая категория "Дополнительно"
- Если указана только одна категория, все поля, не попавшие в неё, автоматически добавляются во вкладку "Дополнительно"
- Если категорий несколько, нераспределенные поля также добавляются в "Дополнительно"
- Если категории не указаны вообще, все поля идут подряд без вкладок
Ширина колонок в ряду
Автоматически рассчитывается на основе количества полей:
- 1 поле:
col-12(полная ширина) - 2 поля:
col-md-6(по половине) - 3 поля:
col-md-4(по трети) - 4 поля:
col-md-3(по четверти)
Примеры использования
Простой диалог создания
const dialog = crud_d.makeDialog('simple_user', {
name: ['text', { label: 'Имя', required: true }, ''],
email: ['email', { label: 'Email', required: true }, '']
});
dialog.setCreateEndpoint('/api/users');
// Открытие
dialog.openCreate('Новый пользователь')
.onSuccess(function(result) {
alert('Пользователь создан!');
});
Диалог с обновлением и удалением
const dialog = crud_d.makeDialog('user_edit', {
name: ['text', { label: 'Имя', required: true }, ''],
email: ['email', { label: 'Email', required: true }, ''],
role: ['select', {
label: 'Роль',
options: [
{ value: 'user', label: 'Пользователь' },
{ value: 'admin', label: 'Администратор' }
]
}, 'user']
});
dialog.setGetEndpoint('/api/users/{id}');
dialog.setUpdateEndpoint('/api/users/{id}');
dialog.setDeleteEndpoint('/api/users/{id}');
// Открытие на редактирование
dialog.openUpdate(42, 'Редактирование пользователя')
.onSuccess(function(result) {
console.log('Обновлен:', result);
// Обновить список пользователей
})
.onDelete(function(id) {
console.log('Удален:', id);
// Удалить из списка
})
.onError(function(error) {
alert('Ошибка: ' + error.message);
});
Сложный диалог с категориями
const dialog = crud_d.makeDialog('product_form', {
name: ['text', { label: 'Название', required: true }, ''],
price: ['number', { label: 'Цена', required: true, min: 0 }, 0],
quantity: ['number', { label: 'Количество', min: 0 }, 0],
category: ['select', {
label: 'Категория',
options: [
{ value: 'electronics', label: 'Электроника' },
{ value: 'clothing', label: 'Одежда' }
]
}, 'electronics'],
description: ['textarea', { label: 'Описание', rows: 5 }, ''],
weight: ['number', { label: 'Вес (кг)', step: 0.1 }, null],
dimensions: ['text', { label: 'Размеры' }, ''],
manufacturer: ['text', { label: 'Производитель' }, ''],
in_stock: ['checkbox', { label: 'В наличии' }, true]
}, {
width: 'lg',
categories: {
'Основное': [
['name'],
['price', 'quantity', 'in_stock'],
['category'],
['description']
],
'Характеристики': [
['weight', 'dimensions'],
['manufacturer']
]
}
});
dialog.setCreateEndpoint('/api/products');
dialog.setGetEndpoint('/api/products/{id}');
dialog.setUpdateEndpoint('/api/products/{id}');
dialog.setDeleteEndpoint('/api/products/{id}');
Глобальное управление
// Регистрируем диалог
crud_d.makeDialog('quick_user', {
name: ['text', { label: 'Имя' }, ''],
email: ['email', { label: 'Email' }, '']
});
// Устанавливаем эндпоинты глобально
crud_d.setCreateEndpoint('quick_user', '/api/users');
crud_d.setGetEndpoint('quick_user', '/api/users/{id}');
// Открываем из любого места
crud_d.openCreate('quick_user', 'Быстрое создание')
.onSuccess(function(result) {
console.log('Готово!', result);
});
// Закрываем при необходимости
crud_d.closeDialog('quick_user');
// Закрыть все открытые диалоги
crud_d.closeAll();
Кастомное поле
// Создаем кастомный элемент для выбора цвета
const colorPicker = document.createElement('div');
colorPicker.className = 'mb-3';
colorPicker.innerHTML = `
<label class="form-label">Цвет товара</label>
<div class="input-group">
<input type="color" class="form-control form-control-color"
value="#563d7c" title="Выберите цвет">
<input type="text" class="form-control" value="#563d7c">
</div>
`;
// Синхронизация инпутов
const [colorInput, textInput] = colorPicker.querySelectorAll('input');
colorInput.addEventListener('input', () => textInput.value = colorInput.value);
textInput.addEventListener('input', () => colorInput.value = textInput.value);
const dialog = crud_d.makeDialog('custom_example', {
name: ['text', { label: 'Название' }, ''],
color: ['custom', colorPicker, '#563d7c']
});
dialog.setCreateEndpoint('/api/products');
dialog.openCreate('Товар с цветом');
Установка значений по умолчанию
dialog.openCreate('Новый заказ')
.setValues({
priority: 'high',
status: 'pending',
date: new Date().toISOString().split('T')[0]
})
.onSuccess(function(result) {
console.log('Заказ создан:', result);
});
События и колбэки
Порядок выполнения
-
Создание (create):
- Валидация формы
- POST запрос на create endpoint
onSuccessпри успехеonErrorпри ошибке- Автоматическое закрытие диалога при успехе
-
Обновление (update):
- GET запрос на get endpoint для загрузки данных
- Заполнение формы полученными данными
- При сохранении: валидация → PUT запрос →
onSuccess/onError - При удалении: подтверждение → DELETE запрос →
onDelete/onError - Автоматическое закрытие диалога при успехе
-
Создание из существующего элемента (create from):
- GET запрос на get endpoint для загрузки данных
- Заполнение формы полученными данными
- Валидация формы
- POST запрос на create endpoint
onSuccessпри успехеonErrorпри ошибке- Автоматическое закрытие диалога при успехе
Цепочка методов
Все методы настройки возвращают this, что позволяет использовать цепочку вызовов:
dialog
.setCreateEndpoint('/api/users')
.setGetEndpoint('/api/users/{id}')
.openCreate('Пользователь')
.onSuccess(handleSuccess)
.onError(handleError);
Обработка ошибок
Библиотека автоматически обрабатывает HTTP ошибки и отображает их в диалоге:
- Ошибки валидации отображаются в alert-блоке внутри диалога
- Ошибки сети/сервера отображаются там же
- Все ошибки также передаются в
onErrorколбэк
dialog.openCreate('Форма')
.onError(function(error) {
// error.message содержит текст ошибки
if (error.message.includes('422')) {
// Ошибка валидации на сервере
} else if (error.message.includes('500')) {
// Ошибка сервера
}
});
Примечания
- Все эндпоинты поддерживают подстановку
{id}в URL - При закрытии диалога через
data-bs-dismiss="modal"он автоматически очищается - Одновременно может быть открыт только один экземпляр диалога с одинаковым dialogId
- Библиотека требует Bootstrap 5 и библиотеку dom.js
- Все HTTP запросы отправляются с заголовком
Content-Type: application/json