DHTMLX Form и Calendar

Компонент DHTMLX form позволяет создавать формы или преобразовывать уже существующие HTML-формы. Форма может иметь следующие элементы:  button, checkbox, container, input, file, hidden, label, multiselect, password, radio, select, template, textarea и upload.

var myForm = appPopup.attachForm([{
    type: "settings",
    position: "label-left",
    labelWidth: 100
}, {
    type: "input",
    label: "No name:",
    inputWidth: 50
}, {
    type: "input",
    name: "input1",
    label: "Some Label:",
    required: true
}, {
    type: "checkbox",
    name: "checkbox1",
    label: "Yes?"
}, {
    type: "calendar",
    name: "mydate",
    label: "date:"
}, {
    type: "select",
    name: "mySelect",
    label: "Select One:",
    options: [{
        text: "Option1",
        value: 1
    }, {
        text: "Option2",
        value: 2
    }, ]
}, {
    type: "button",
    name: "myButton1",
    value: "Click Me"
}, {
    type: "block",
    list: [{
        type: "button",
        value: "Button Left"
    }, {
        type: "newcolumn",
        offset: 55
    }, {
        type: "button",
        value: "Button Right"
    }, ]
}]);

Элемент типа settings задает общие свойства для всех элементов формы. Но элементы могут перекрывать эти значения своими значениями.

У элемента типа input могут быть следующие атрибуты: inputWidth, validate, required, label и name. Атрибут validate может принимать значения ValidSSN, ValidNumeric, Empty, NotEmpty и ValidEmail. Можно указать имя функции для валидации или задать регулярное выражение. Можно через запятую перечислить несколько правил например указать  NotEmpty и ValidNumeric. Также есть атрибут required, который эквивалентен правилу NotEmpty.

Элементы типа hidden эквиваленты HTML input элементам типа hidden.

Элементы типа checkbox принимают значение 0 или 1. К ним можно применить атрибуты required и validate.

Элементы типа calendar инициализируются компонентом DHTMLX calendar. Через атрибут dateFormat можно указать формат отображения.

У элементов типа select в свойстве options хранятся возможные варианты выбора. Каждый вариант имеет атрибут selected.

Для группировки элементов применяется тип block.

Элементы типа newcolumn позволяют создать новый столбец. Все элементы следующие за таким элементом попадают в новый столбец. Через атрибут offset можно задать расстояние между столбцами.


Большинство элементов формы имеет следующие атрибуты:
• className (string): It adds a CSS class to item
• disabled (Boolean): It disables or enables the item
• hidden (Boolean): It shows or hides the item
• tooltip (string): It sets a tooltip for the item
• name (string): It is the name of the form elemen

Методы:
myForm.setItemFocus("input1");

myForm.validate();

myForm.clear();

myForm.enableLiveValidation(true);

myForm.setFormData({ input1: "Hello!" });

myForm.getFormData();

Добавим в app.js следующий код:
// Form
var appForm;
dhtmlxEvent(window, "load", function() {
    // create form
    appForm = appPopup.attachForm([
    // settings
    {
        type: "settings",
        position: "label-left",
        labelWidth: 130,
        inputWidth: 120
    },
    // id
    {
        type: "hidden",
        name: "id"
    },
    // firstName
    {
        type: "input",
        name: "firstName",
        required: true,
        label: "First Name:"
    },
    // middleInitial
    {
        type: "input",
        name: "middleInitial",
        label: "Middle Initial:",
        inputWidth: 50
    },
    // lastName
    {
        type: "input",
        name: "lastName",
        required: true,
        label: "Last Name:"
    },
    // dob
    {
        type: "calendar",
        enableTime: false,
        dateFormat: "%n-%j-%Y",
        name: "dob",
        required: true,
        label: "Date of Birth:",
        inputWidth: 80
    },
    // email
    {
        type: "input",
        name: "email",
        required: true,
        validate: "ValidEmail",
        label: "Email:"
    },
    // active
    {
        type: "checkbox",
        name: "active",
        label: "Active:"
    },
    // buttons
    {
        type: "block",
        width: 300,
        list: [{
            type: "button",
            value: "Save",
            name: "save"
        }, {
            type: "newcolumn"
        }, {
            type: "button",
            value: "Cancel",
            name: "cancel"
        }]
    }]);

    // enable validation
    appForm.enableLiveValidation(true);

    // set event
    appForm.attachEvent("onButtonClick", function(btnName) {
        // save or cancel
        if (btnName == "cancel") {
            callbacks.hidePopup();
        } else if (appForm.validate()) {
            var formData = appForm.getFormData();
            if (formData.id) {
                storage.updateUser(formData);
            } else {
                storage.createUser(formData);
            }
            callbacks.hidePopup();
        }
    });
});

Также изменим объект callbacks:
showPopup: function(){
 appPopup.setModal(1);
 appPopup.show();
 appForm.setItemFocus("firstName");
},

hidePopup: function(){
 appPopup.setModal(0);
 appPopup.hide();
 appForm.clear();
},

editClick: function(userId){
 // get user
 var user = storage.getUser(userId);
 // load user into popup
 appForm.setFormData(user);
 // show popup
 callbacks.showPopup();
},

Должно получиться так:

Подправим CSS в index.html:
body, html { height: 100%; width: 100%; }
.dhxform_base { margin: 25px; }
.dhxform_base .dhxform_base { margin: 20px 15px;}