Хочу поделиться с обществом собственным плагином, который упрощает работу с динамическими формами и называется jqDynaForm. Под динамическими формами я подразумеваю формы, в которые при заполнении пользователь может добавлять по необходимости дополнительные поля или блоки полей. Разумеется, в каждом месте разрешено добавлять только заранее разрешенные виды блоков. Вот примеры подобных простейших форм:
1. Контактная форма, в которой есть поле «телефон». Пользователь может добавить еще несколько дополнительных полей для телефонов, если возникнет желание.
2. Счет на оплату. Есть фиксированный набор полей, таких как «имя плательщика» и «номер счета». Кроме того, есть таблица с позициями. Каждая позиция состоит следующих полей: «наименование», «количество», «цена». Пользователь может добавлять произвольное количество дополнительных позиций.
Давайте рассмотрим работу с jqDynaForm на примере такого счета. Вот пример такой формы:
Давайте посмотрим на HTML код, который необходимо приготовить для плагина:
<!-- Base form -->
<h1>Simple form demo</h1>
<div id="smallForm">
<h2>Invoice</h2>
<p>Number: <input name="number" size="6"> Payer: <input name="payer"></p>
<h3>Products</h3>
<div data-holder-for="product"></div>
<p> </p>
<input type="button" value="Save" id="saveSmallForm">
</div>
<!-- Library of dynamic blocks. Here is only one block named "product" -->
<div style="display:none">
<div data-name="product" data-label="Product" class="product">
<input name="title" style="width:600px">
Price: <input name="price" style="width:100px; text-align:right">
X <input name="amount" class="short" value="1" style="width:50px">
</div>
</div>
Выкину все лишнее, чтобы стало нагляднее:
<!--Базовая форма -->
<div>
… Фиксированные поля формы…
<div data-holder-for="<ПУНКТ_СЧЕТА>"></div>
<input type="button" value="Save">
</div>
<!--Код для динамической вставки-->
<div data-name="ПУНКТ_СЧЕТА">
… Поля отдельного пункта счета …
</div>
Т.е. у нас есть некая базовая форма с фиксированным набором полей. Внутри этой формы мы размещаем холдер, DIV помеченный атрибутом «data-holder-for». Значение атрибута задает имя блока, который сюда можно вставлять. HTML код этого блока задается отдельно от формы и помечается атрибутом data-name.
Кнопки добавление, удаления пунктов, поведение drag-and-drop для сортировки и переноса полностью формируется плагином.
API
Чтобы получить значения полей формы надо сделать следующий вызов
var json = $(<ФОРМА>).jqDynaForm('get');
и он вернут JSON объект следующей структуры:
{
"number": "123",
"payer": "Fake Incorporated",
"productArray": [
{
"title": "HP Pavilion g7-2010nr 17.3-Inch",
"price": "499.99",
"amount": "3"
},
{
"title": "Samsung Galaxy Tab 2 (7-Inch, Wi-Fi)",
"price": "248.00",
"amount": "1"
},
{
"title": "HP Envy 4-1030us 14-Inch Ultrabook",
"price": "779.99",
"amount": "1"
}
]
}
Обратите внимание, что повторяющиеся вложенные блоки автоматически размещаются в массивах. Значения ключей в полях, это атрибут name в тегах INPUT и SELECT.
Если у вас есть уже такой готовый JSON объект (сформированный скриптом, или считанный из базы данных), то вы можете при помощи одного вызова воссоздать форму.
$(<ПУСТАЯ_БАЗОВАЯ_ФОРМА>).jqDynaForm('set', json);
После этого вызова мы получим исходную форму с заполненными полями и сформированными вложенными блоками. Разумеется, при наличии правильной исходной формы и подготовленных блоков полей.
Пример посложнее
На самом деле, структура формы может быть гораздо сложней, потому что вы можете размещаться холдеры не только в базовой форме, но и внутри динамических блоков. Холдер даже может ссылаться на самого себя, формирую древовидную рекурсивную структуру. Вот пример более сложной формы:
Фичи
Перечислю наиболее важные фичи:
- Произвольный HTML код формы без особых ограничений
- Строгое задание структуры иерархии вложения блоков
- Создание вложенности в несколько уровней
- Создание рекурсивных структур
- Действия над структурой при заполнении формы: Добавление блока, удаление блока, сортировка и перенос (drug-and-drop) блока в другое разрешенное место.
- Превращение формы любой структуры в JSON объект
- Воссоздание формы из JSON объекта
- Создание формы без необходимости программирования. Настройка задается специальными атрибутами
Также планирую добавить следующее возможности:
- Упрощенный механизм валидации полей по регулярным выражениям
- Внешние обработчики событий
Работа с JSON
Как работать с полученной JSON структурой. Можно обрабатывать на JavaScript-е, можно отправить на сервер и превратить, например в php-array древовидную структуру.
Обычно значения полей хранят в базах данных. С классическими «плоскими» формами все понятно. Такая форма замечательно ложиться в одну запись таблицы реляционной базы данных. А тут форма древовидная, и структура данных соответственно тоже древовидная. Вариантов хранения много, вот некоторые:
- Использование MongoDB (Самый красивый вариант)
- Хранения JSON объекта в виде текста в обычной реляционной БД. Но это не всегда приемлемо, если необходимо выполнять запросы к отдельным поля формы. Поэтому рассмотрим следующий, компромиссный вариант
- Хранения полей верхнего уровня в полях реляционной БД, а всех полей вложенных блоков в виде текстового представления JSON объектов в дополнительных полях той же записи реляционной БД.
- Самый занудный вариант, это завести для каждого вида блока полей отдельную таблицу в реляционной БД и заполнять эти таблицы «вручную», оббегая JSON объект.
Что меня побудило к созданию этого плагина
Я много занимаюсь разработкой разного рода веб-приложений. Многие приложения содержат большое количество форм. Создание обработчиков форм часто отнимают много времени. Есть разного рода решения, которые упрощают создание обычных, плоских форм. Но когда требуются динамические формы, то тут стандартные решения, как правило, уже мало помогают.
Вот типичный ход работы над проекта в стиле «ночной кошмар». От Заказчика с некоторым периодом поступают следующие требования:
- Сделайте форму для хранения данных о компании. Там надо только поля «название», «город», «улица», «дом».
- Ой! Оказывается у компании может быть много филиалов. Сделайте, чтобы можно было в форме задать адрес каждого филиала по отдельности.
- Мы тут подумали, нам бы еще надо, чтобы у каждой компании в форме можно было записать несколько проектов, которые она выполняла.
- Добавьте, пожалуйста, контактное лицо к каждому филиалу. А… Добавили? А как к каждому телефону указать имя человека? … Нам надо чтобы можно было задать много контактных лиц в каждом филиале и каждому указать отдельный телефон.
Дабы избежать кошмара постоянного программирования всех этих кнопочек – «добавить», «удалить», «перенести», не мучаться с формированием динамических структур, удобно обрабатывать значения полей, я и задумался на созданием этого плагина.
Исходники
Заранее предупреждаю, что плагин еще сырой. Но если у общества будет интерес, то я планирую его дорабатывать и выкладывать следующие версии.
Страничка проекта находится на Google Code
Скачать рабочий пример и исходники можно здесь
А здесь, можно поиграть с живым примером
Автор: tushev