Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e314044ac |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.idea/
|
||||
43
README.md
43
README.md
@ -35,10 +35,11 @@
|
||||
|
||||
## Основные концепции
|
||||
|
||||
Библиотека работает с двумя основными режимами открытия диалога:
|
||||
Библиотека работает с тремя основными режимами открытия диалога:
|
||||
|
||||
- **create** — создание нового элемента (пустая форма)
|
||||
- **update** — редактирование существующего элемента (форма с подгруженными данными)
|
||||
- **create from** — создание нового элемента из существующего (форма с подгруженными данными)
|
||||
|
||||
Каждый диалог имеет:
|
||||
- Уникальный строковый идентификатор (dialogId)
|
||||
@ -143,6 +144,19 @@ dialog.openUpdate(42, 'Редактирование пользователя')
|
||||
});
|
||||
```
|
||||
|
||||
#### openCreateFrom(itemId, title)
|
||||
Открывает диалог в режиме создания с загруженными данными через GET endpoint.
|
||||
|
||||
```javascript
|
||||
dialog.openUpdate(42, 'Создание копии пользователя')
|
||||
.onSuccess(function(result) {
|
||||
console.log('Создана копия:', result);
|
||||
})
|
||||
.onError(function(error) {
|
||||
console.error('Ошибка:', error);
|
||||
});
|
||||
```
|
||||
|
||||
#### getConfig()
|
||||
Возвращает текущую конфигурацию диалога.
|
||||
|
||||
@ -196,6 +210,16 @@ api.onDelete(function(itemId) {
|
||||
});
|
||||
```
|
||||
|
||||
#### onOpen(callback)
|
||||
Устанавливает обработчик успешного открытия. Если диалог открыт
|
||||
в режиме редактирования, функция будет вызвана после загрузки всех данных.
|
||||
|
||||
```javascript
|
||||
api.onOpen(function() {
|
||||
console.log('Диалог открыт и загружен');
|
||||
});
|
||||
```
|
||||
|
||||
#### setValues(values)
|
||||
Устанавливает значения полей формы.
|
||||
|
||||
@ -270,6 +294,14 @@ crud_d.openUpdate('user_form', 42, 'Редактирование')
|
||||
});
|
||||
```
|
||||
|
||||
#### openCreateFrom(dialogId, itemId, title)
|
||||
```javascript
|
||||
crud_d.openUpdate('user_form', 42, 'Копирование')
|
||||
.onSuccess(function(result) {
|
||||
console.log('Создан из объекта:', result);
|
||||
});
|
||||
```
|
||||
|
||||
#### closeDialog(dialogId)
|
||||
```javascript
|
||||
crud_d.closeDialog('user_form');
|
||||
@ -648,6 +680,15 @@ dialog.openCreate('Новый заказ')
|
||||
- При удалении: подтверждение → DELETE запрос → `onDelete`/`onError`
|
||||
- Автоматическое закрытие диалога при успехе
|
||||
|
||||
3. **Создание из существующего элемента (create from):**
|
||||
- GET запрос на get endpoint для загрузки данных
|
||||
- Заполнение формы полученными данными
|
||||
- Валидация формы
|
||||
- POST запрос на create endpoint
|
||||
- `onSuccess` при успехе
|
||||
- `onError` при ошибке
|
||||
- Автоматическое закрытие диалога при успехе
|
||||
|
||||
### Цепочка методов
|
||||
|
||||
Все методы настройки возвращают `this`, что позволяет использовать цепочку вызовов:
|
||||
|
||||
48
crud_d.js
48
crud_d.js
@ -1,4 +1,3 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// Хранилище зарегистрированных диалогов
|
||||
@ -323,6 +322,7 @@
|
||||
const options = {
|
||||
method,
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content ?? '',
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
};
|
||||
@ -365,7 +365,7 @@
|
||||
|
||||
// Заголовок
|
||||
const header = dom.div().cls('modal-header');
|
||||
const titleText = mode === 'create' ? title : `Редактирование: ${title}`;
|
||||
const titleText = mode === 'create' ? title : mode === 'create_from' ? `Скопировать из: ${title}` : `Редактирование: ${title}`;
|
||||
const titleEl = dom.h5().cls('modal-title').text(titleText);
|
||||
const closeBtn = dom.button().cls('btn-close').atr('data-bs-dismiss', 'modal').atr('aria-label', 'Close');
|
||||
header.child(titleEl);
|
||||
@ -413,7 +413,7 @@
|
||||
const categoryNames = Object.keys(finalCategories);
|
||||
|
||||
const tabNav = dom.ul().cls('nav nav-tabs').atr('role', 'tablist');
|
||||
const tabContent = dom.div().cls('tab-content');
|
||||
const tabContent = dom.div().cls('tab-content').cls('mt-3');
|
||||
|
||||
categoryNames.forEach((catName, index) => {
|
||||
const tabId = `tab_${dialogId}_${catName.replace(/[^a-zA-Z0-9]/g, '_')}`;
|
||||
@ -475,7 +475,7 @@
|
||||
const submitSpinner = dom.span().cls('spinner-border spinner-border-sm').atr('role', 'status')
|
||||
.atr('aria-hidden', 'true').css('display: none');
|
||||
|
||||
if (mode === 'create') {
|
||||
if (mode === 'create' || mode === 'create_from') {
|
||||
submitBtn.text('Создать');
|
||||
submitBtn.child(submitSpinner);
|
||||
footer.child(cancelBtn);
|
||||
@ -630,6 +630,10 @@
|
||||
return this._open(title, 'create');
|
||||
},
|
||||
|
||||
openCreateFrom: function(itemId, title = 'Скопировать из') {
|
||||
return this._open(title, 'create_from', itemId);
|
||||
},
|
||||
|
||||
// Открытие в режиме обновления
|
||||
openUpdate: function(itemId, title = 'Редактирование') {
|
||||
return this._open(title, 'update', itemId);
|
||||
@ -648,6 +652,10 @@
|
||||
activeDialogs.set(dialogId, modal);
|
||||
|
||||
const api = {
|
||||
onOpen: function(callback) {
|
||||
modal.onOpen = callback;
|
||||
return this;
|
||||
},
|
||||
onSuccess: function(callback) {
|
||||
modal.onSuccess = callback;
|
||||
return this;
|
||||
@ -681,7 +689,7 @@
|
||||
};
|
||||
|
||||
// Загрузка данных для режима update
|
||||
if (mode === 'update' && itemId) {
|
||||
if ((mode === 'update' || mode === 'create_from') && itemId) {
|
||||
modal.showLoadingOverlay();
|
||||
|
||||
const getEndpoint = config.endpoints.get;
|
||||
@ -698,6 +706,9 @@
|
||||
.then(data => {
|
||||
modal.setValues(data);
|
||||
modal.hideLoadingOverlay();
|
||||
if (typeof modal.onOpen === 'function') {
|
||||
modal.onOpen(modal);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
modal.hideLoadingOverlay();
|
||||
@ -705,6 +716,14 @@
|
||||
});
|
||||
}
|
||||
|
||||
if (mode === 'create') {
|
||||
setTimeout(() => {
|
||||
if (typeof modal.onOpen === 'function') {
|
||||
modal.onOpen(modal);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Обработчик сохранения/создания
|
||||
modal.submitBtn.addEventListener('click', async () => {
|
||||
const errors = modal.validate();
|
||||
@ -720,7 +739,7 @@
|
||||
const formData = modal.getFormData();
|
||||
let result;
|
||||
|
||||
if (mode === 'create') {
|
||||
if (mode === 'create' || mode === 'create_from') {
|
||||
const createEndpoint = config.endpoints.create;
|
||||
if (!createEndpoint) {
|
||||
throw new Error('Create endpoint не установлен');
|
||||
@ -823,8 +842,6 @@
|
||||
return dialogApi;
|
||||
},
|
||||
|
||||
// Глобальные методы для работы по имени диалога
|
||||
|
||||
// Установка эндпоинтов по имени диалога
|
||||
setCreateEndpoint: function(dialogId, endpoint) {
|
||||
const dialog = dialogs.get(dialogId);
|
||||
@ -876,6 +893,19 @@
|
||||
}
|
||||
},
|
||||
|
||||
openCreateFrom: function(dialogId, itemId, title = 'Скопировать из') {
|
||||
const dialog = dialogs.get(dialogId);
|
||||
if (dialog) {
|
||||
const api = this.makeDialog(dialogId, dialog.fields, dialog.options);
|
||||
// Копируем эндпоинты
|
||||
api.getConfig().endpoints = dialog.endpoints;
|
||||
return api.openCreateFrom(itemId, title);
|
||||
} else {
|
||||
console.error(`Диалог "${dialogId}" не найден`);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
openUpdate: function(dialogId, itemId, title = 'Редактирование') {
|
||||
const dialog = dialogs.get(dialogId);
|
||||
if (dialog) {
|
||||
@ -907,5 +937,3 @@
|
||||
activeDialogs.clear();
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
Loading…
x
Reference in New Issue
Block a user