![](https://habrastorage.org/files/ed5/ac3/163/ed5ac316305641808ba1c6742e1905ea.png)
Создание форм с помощью чистого HTML задача довольно тривиальная и подробно обсуждается в каждом уважающем себя учебнике. Но все становится куда сложнее, если вам нужно, например, разнести элементы формы по нескольким табам. В этом случае без фреймворка не обойтись. В этой статье я расскажу, как можно создать сложные веб-формы с помощью UI-фреймворка Webix.
Основы. Как создать простую форму
Сперва давайте разберемся с тем, как можно создать форму с помощью Form Component. В Вебикс все элементы интерфейса описываются через JSON. Для создания формы нужно использовать объект со свойство
view:"form"
. У этого же объекта нужно задать свойство elements
— это массив, содержащий элементы, из которых состоит ваша форма.Вот как это работает:
webix.ui({
view:"form",
elements: [
{ /* первый компонент формы */ },
{ /* второй компонент формы */},
{ /* и т.д. */}
]
});
В качестве элемента формы можно использовать любой другой компонент Webix UI: текстовое поле, чекбокс, кнопку и т.п.
Для того, чтобы увидеть, как все это работает на практике, давайте создадим простую форму в качестве примера. Для этого нам понадобятся: два текстовых поля: одно для имени пользователя и одно для пароля; один чекбокс, чтобы быть уверенными в том, что пользователь принимает условия соглашения; и последний элемент — кнопка Submit.
Итак, код:
webix.ui({
view:"form",
id:"myForm",
container: "areaA",
width: 350,
elements: [
{view:"text", label:"Username", name:"username"},
{view:"text", label:"Password", name:"password",
type:"password"},
{view:"checkbox", labelRight:"I accept terms of use",
name:"accept"},
{view:"button", value: "Submit", width: 150, align:"center",
click:submit}
]
});
Ничего такого, к чему бы мы не были готовы. Свойство
view:"form"
uговорит о том, что нас интересует именно форма. Свойства label
работают также, как и HTML тег label
. Получить значение каждого элемента формы можно через свойство name
. Для того, чтобы скрыть вводимые символы в поле Password, используется свойство type:"password"
. Что интересно, так это свойство click:submit
в коде описания кнопки. Оно определяет функцию, которая будет вызвана после того, как кнопка будет нажата. Это свойство необязательно, но будет полезно проверить с его помощью, всё ли хорошо с введенными данными.Вот пример кода, который выводит на экран введенные значения. Для вывода сообщений в нем используется Webix Message Box:
function submit(){
webix.message(JSON.stringify($$("myForm").getValues(), null, 2));
}
В этом примере с помощью метода getValues()мы получаем значения элементов Webix, а метод JSON.stringify() служит для преобразования полученных данных в строку JSON.
Итак, все готово и мы можем проверить результат:
![](https://habrastorage.org/files/e4a/397/d89/e4a397d89c5c42e391aed9c17912e9be.png)
После ввода данных можно проверить работу формы с помощью кнопки Submit:
![](https://habrastorage.org/files/cc6/3c5/e5d/cc63c5e5deb94755a9f944f46361fb00.png)
Все работает как и положено. Поскольку нам теперь известны основы создания форм, можно попробовать создать что-то более сложное.
Код и демо можно глянуть здесь — webix.com/snippet/2259ec41
Использование сложных контролов на примере Multicombo
Webix предоставляет несколько контролов, помогающих пользователю с выбором во время работы с формами. На мой взгляд, один из самых интересных из них это Multicombo. Этот контрол позволяет реализовать множественный выбор из элементов выпадающего списка.
Например, вы хотите создать страницу для создания резюме разработчика. Вот упрощенный пример формы, которую вы можете использовать:
![](https://habrastorage.org/files/62d/30a/79f/62d30a79fbcb43a4919ffb86037a5a79.png)
Поскольку вполне вероятно, что пользователь владеет более чем одним языком программирования и вы вооружены списком языков, это тот самый случай, когда можно использовать Multicombo. Вот пример файла data.js, который содержит нужные данные:
var languages = [
{id:1, lang:"4th Dimension/4D"},
{id:2, lang:"ABAP"},
/* и т.д. */
]
Давайте используем Multicombo в поле Skills:
{view:"multicombo", name:"skills", label:"Skills", button: true,
suggest: {
body:{
data:languages,
template:webix.template("#lang#")
}
},
}
Помимо уже знакомых нам свойств, в этом примере имеется и что-то новое. Свойство
button: true
создаст кнопку подтверждения выбора в выпадающем списке. Для того, чтобы указать источник содержимого для выпадающего списка используется свойство suggest
. Можно, например, просто указать путь к файлу: suggest: "path/to/file/data.js"
. Но лучше всего использовать шаблон в комбинации со свойством data
, что позволит извлечь из целевого архива именно те данные, которые вам нужны.Ниже показан пример работы такого контрола. После клика в текстовом поле появится выпадающее меню с доступными для выбора вариантами:
![](https://habrastorage.org/files/aab/ce8/85e/aabce885e9bf4a15baacd12b1c144302.png)
Можно промотать список и выбрать нужные варианты или начать вводить текст:
![](https://habrastorage.org/files/e72/c98/5f3/e72c985f324b4663a52c4683797232a1.png)
Форма из этого примера вернет список ID выбранных пунктов:
![](https://habrastorage.org/files/780/99b/166/78099b166f7f4b11ac92e615568fe6ab.png)
Код и демо можно глянуть здесь — webix.com/snippet/63f6328e
Полезными также могут оказаться такие контролы как Grid Suggest и Dataview Suggest
Использование дерева как элемента формы
Webix не ограничивает вас использованием текстовых полей, кнопок, чекбоксов и прочих привычных компонентов в качестве элементов формы. В форму можно поместить практически любой виджет. Давайте попробуем сделать это на примере Tree. Он не был изначально предназначен для использования внутри формы, поэтому он не имеет методов
setValue()
и getValue()
, необходимых для получения данных о выбранных элементах. Как это можно исправить? Можно использовать метод protoUI, который позволяет создавать новые элементы на основе уже имеющихся:webix.protoUI({
name:"formTree",
setValue:function(value){ this.checkItem(value); },
getValue:function(){ return this.getChecked(); }
}, webix.ui.tree);
В этом примере мы создали новый компонент, который называется
formTree
. Затем мы определили для него методы setValue()
и getValue()
. И, наконец, указали, что хотим создать новый компонент на основе дерева. Прежде чем его использовать, давайте создадим необходимые данные для нашего дерева:
var treedata = [
{ id: "1", value: "Web", data: [
{ id: "1.1", value: "HTML" },
{ id: "1.2", value: "CSS" },
/* some more data */
]},
{id:"2", value:"Scripting", data: [
{ id: "2.1", value: "Shell" },
/* some more data here */
]},
]
Теперь можно добавить новый элемент в форму. Сделать это можно так же, как и в случае с любым другим элементом:
{view:"formTree", name:"skills", data:treedata,
height: 150, threeState: true,
template: "{common.icon()} {common.checkbox()} #value#"
},
Свойство
threeState:true
включает 3-state checkboxes, а шаблон добавляет чекбоксы к узлам дерева.Результат:
![](https://habrastorage.org/files/d22/1e3/3ca/d221e33ca14146ba9acf5fecac9c88c4.png)
Для того, чтобы проверить, насколько хорошо работают определенные нами методы для нового компонента:
![](https://habrastorage.org/files/cfd/8be/f92/cfd8bef92f9c4db79d3fc57a71f21722.png)
Код и демо можно глянуть здесь — webix.com/snippet/9f166141
Формы с табами и Многошаговые формы
Если вы хотите создать достаточно большую форму, может оказаться полезной возможность разделить ее на несколько табов или создать многошаговую форму. Webix позволяет поместить внутрь формы разные UI компоненты, чтобы добиться нужного результата.
Добавляем табы с помощью Tabview
Tabview component позволяет создать набор компонентов с таббаром, служащим для переключения между ними. В качестве содержимого каждого таба можно использовать отдельный компонент или создать свой собственный лэйаут с помощью свойств
rows
и cols
.Вот как работает Tabview:
view:"tabview",
/* содержимое элемента */
cells: [
{
header:"First tab label",
body: {
/* содержимое первого таба */
}
},
{
header:"Second tab label",
body: {
rows:[
{ /* содержимое первого ряда */},
{ /* содержимое второго ряда */}
]
}
},
/* и т.д. */
]
Главная идея этого подхода состоит в том, чтобы поместить Tabview с нужными полями внутри формы. Однако, стоит помнить о том, что компоненты, общие для всей формы (например, кнопка Submit или чекбокс «I agree») должны располагаться за пределами Tabview.
Например:
view:"form",
elements:[
{view:"tabview", height:250,
cells:[
/* заголовок и содержимое 1-го таба */
{header:"Personal Info",
body:{
rows:[
{view:"text", label:"Name", name:"name"},
/* еще поля */
]
}
},
/* заголовок и содержимое 2-го таба */
{header:"Delivery Details",
body:{
rows:[
/* еще немножко полей */
]
}
}
]
}, /* здесь кончается Tabview */
{view:"button", value: "Submit", width: 150,
align:"center", click:submit}
]
Это все, что вам нужно для создания формы с табами. Ниже приведен результат:
![](https://habrastorage.org/files/4eb/3f7/42d/4eb3f742d9ed4ea5b10032fb0948d47a.png)
Лучшая часть всей этой истории состоит в том, что вам не нужно писать какой-то дополнительный код, чтобы разные части формы работали как единое целое. Просто поместите Tabview внутрь формы и не забудьте про свойство
name
для каждого ее элемента.Кнопка Submit это подтверждает:
![](https://habrastorage.org/files/784/f9c/ffb/784f9cffb2d24989b16c5f9a76f5799c.png)
Код и демо можно глянуть здесь — webix.com/snippet/79eb2712
В качестве альтернативы табам, вы можете попробовать, например, Accordion.
Создание многошаговой формы с помощью Multiview
Multiview позволяет создавать последовательность элементов и просматривать их один за другим, что позволяет экономить место на экране. Более того, переключение происходит с эффектом анимации! Можно создать табы для переключения между компонентами, но, поскольку нас интересует многошаговая форма, давайте используем кнопки для нашего примера.
В первую очередь нам понадобятся функции для перехода между элементами формы:
function next(){
var parentCell = this.getParentView().getParentView();
var index = $$("formCells").index(parentCell);
var next = $$("formCells").getChildViews()[index+1]
if(next)
next.show();
}
function back(){
$$("formCells").back();
}
Этот код использует значение ID элемента Multiview, так что не забудьте установить его. Что касается кода формы, он практически не изменяется. Нам нужно только изменить содержимое массива
elements
. Сам компонент Multiview создается схожим образом с элементом Tabview из прошлого примера. На этот раз нам нужно добавить внутрь этого компонента дополнительный ряд, который будет содержать кнопки управления.Вот как это можно сделать:
{view:"multiview", id:"formCells", cells: [
/* 1-й шаг формы */
{rows:[
{/* определение полей */},
{cols:[
/* кнопки */
{}, /* пустой элемент */
{view:"button", value:"Next", click:next}
]}
]},
/* 2-й шаг формы */
{rows:[
{/* ещё поля */},
{cols:[
/*кнопки*/
{view:"button", value:"Back", click:back},
{view:"button", value:"Next", click:next}
]}
]},
/* последний шаг формы */
{rows:[
{/* поля... */},
{cols:[
/*кнопки*/
{view:"button", value:"Back", click:back },
{view:"button", value:"Submit", click:submit}
]}
]}
]}
Давайте посмотрим на результат:
![](https://habrastorage.org/files/db9/640/0fc/db96400fc38c41eaa16750e8c505c7da.png)
После нажатия кнопки Next, появится следующая часть формы:
![](https://habrastorage.org/files/b5c/510/d9c/b5c510d9c76b4ebd9d5e6f13a986216f.png)
А теперь давайте проверим введенные данные:
![](https://habrastorage.org/files/9a3/ebe/81b/9a3ebe81b0d94b47b089e113515d7658.png)
Все работает.
Код и демо можно глянуть здесь — webix.com/snippet/39464194
Заключение
Webix позволяет вам создавать практически любые комбинации компонентов. Внутрь формы можно поместить любой виджет или контрол. Если вас не устраивает функционал определенного компонента, можно создать на его основе свой собственный с помощью
protoUI
и, опять-таки, поместить его в форму. Таким образом, практически ничто не ограничивает вашу фантазию.