Розробка конструктора форм на 1С-Бітрікс

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Пропоновані послуги
Показано 1 з 1 послугУсі 1626 послуг
Розробка конструктора форм на 1С-Бітрікс
Середня
~1-2 тижні
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    585
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    751
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    989

Розробка конструктора форм на 1С-Бітрікс

Конструктор форм — інструмент, що дозволяє менеджеру або маркетологу самостійно створювати довільні форми без розробника. Додати поле, змінити порядок, задати валідацію, налаштувати куди надсилати дані — все через веб-інтерфейс. 1С-Бітрікс має вбудований модуль form (Веб-форми), але він має серйозні обмеження: застарілий інтерфейс, відсутність адаптивного UI, складність інтеграції із зовнішніми системами. Кастомний конструктор вирішує ці обмеження.

Що зберігати

Форма — це метадані (набір полів і правила) плюс результати (заповнені дані). Зберігання через HL-блоки:

Таблиця форм (b_hl_form_builder):

class FormBuilderTable extends \Bitrix\Main\ORM\Data\DataManager
{
    public static function getTableName(): string { return 'b_hl_form_builder'; }

    public static function getMap(): array
    {
        return [
            new IntegerField('ID', ['primary' => true, 'autocomplete' => true]),
            new StringField('TITLE'),
            new StringField('SLUG'),          // URL-ідентифікатор
            new TextField('FIELDS_JSON'),     // Опис полів
            new TextField('SETTINGS_JSON'),   // Налаштування форми
            new BooleanField('IS_ACTIVE', ['values' => [false, true]]),
            new IntegerField('SUBMISSIONS_COUNT'),
            new DatetimeField('CREATED_AT'),
        ];
    }
}

FIELDS_JSON — масив полів з повною конфігурацією:

[
  {
    "id": "field_name",
    "type": "text",
    "label": "Ваше ім'я",
    "placeholder": "Іван Іванов",
    "required": true,
    "width": "half"
  },
  {
    "id": "field_phone",
    "type": "tel",
    "label": "Телефон",
    "required": true,
    "mask": "+7 (000) 000-00-00",
    "width": "half"
  },
  {
    "id": "field_service",
    "type": "select",
    "label": "Послуга",
    "options": ["Розробка", "Аудит", "Підтримка"],
    "required": true
  },
  {
    "id": "field_message",
    "type": "textarea",
    "label": "Повідомлення",
    "rows": 4,
    "required": false
  }
]

SETTINGS_JSON — поведінка форми:

{
  "submit_text": "Надіслати заявку",
  "success_message": "Дякуємо! Ми зв'яжемося з вами.",
  "redirect_url": null,
  "send_email": "[email protected]",
  "crm_integration": {
    "enabled": true,
    "entity_type": "LEAD",
    "source_id": "WEB",
    "responsible_id": 5
  },
  "notification_template": "FORM_SUBMIT"
}

Таблиця результатів (b_hl_form_submissions):

class FormSubmissionTable extends \Bitrix\Main\ORM\Data\DataManager
{
    public static function getTableName(): string { return 'b_hl_form_submissions'; }

    public static function getMap(): array
    {
        return [
            new IntegerField('ID', ['primary' => true, 'autocomplete' => true]),
            new IntegerField('FORM_ID'),
            new TextField('DATA_JSON'),       // Заповнені дані
            new StringField('USER_IP'),
            new StringField('USER_AGENT'),
            new IntegerField('USER_ID'),      // NULL якщо анонімний
            new IntegerField('CRM_ENTITY_ID'),// ID створеного ліда/угоди
            new DatetimeField('CREATED_AT'),
        ];
    }
}

Інтерфейс конструктора (адміністративна частина)

Інтерфейс — drag-and-drop редактор полів. Реалізується в /local/admin/form_builder.php або як окрема React/Vue-сторінка в /local/assets/form-builder/.

Спрощена версія — без drag-and-drop, просто додавання полів через кнопку і сортування стрілками. Це швидше в розробці і достатньо для більшості завдань.

// Простий конструктор полів без drag-and-drop
class FormBuilder {
    constructor(containerId) {
        this.container = document.getElementById(containerId);
        this.fields    = [];
        this.bindEvents();
    }

    addField(type) {
        const id    = 'field_' + Date.now();
        const field = {id, type, label: '', required: false, options: []};
        this.fields.push(field);
        this.renderFields();
        return field;
    }

    removeField(fieldId) {
        this.fields = this.fields.filter(f => f.id !== fieldId);
        this.renderFields();
    }

    moveField(fieldId, direction) {
        const idx = this.fields.findIndex(f => f.id === fieldId);
        if (direction === 'up' && idx > 0) {
            [this.fields[idx-1], this.fields[idx]] = [this.fields[idx], this.fields[idx-1]];
        } else if (direction === 'down' && idx < this.fields.length - 1) {
            [this.fields[idx], this.fields[idx+1]] = [this.fields[idx+1], this.fields[idx]];
        }
        this.renderFields();
    }

    getFieldsJson() {
        // Зібрати актуальні значення з DOM
        this.fields = this.fields.map(field => {
            const row = this.container.querySelector(`[data-field-id="${field.id}"]`);
            if (!row) return field;
            return {
                ...field,
                label:    row.querySelector('.field-label').value,
                required: row.querySelector('.field-required').checked,
                placeholder: row.querySelector('.field-placeholder')?.value || '',
            };
        });
        return JSON.stringify(this.fields, null, 2);
    }
}

Рендер форми на фронтенді

Компонент-рендерер читає JSON-конфігурацію і будує HTML форми:

// /local/components/local/form.builder.render/class.php
class FormBuilderRenderComponent extends \CBitrixComponent
{
    public function executeComponent(): void
    {
        $formSlug = $this->arParams['FORM_SLUG'] ?? '';
        $form     = FormBuilderTable::getList([
            'filter' => ['SLUG' => $formSlug, 'IS_ACTIVE' => true],
        ])->fetch();

        if (!$form) {
            $this->arResult['NOT_FOUND'] = true;
            $this->includeComponentTemplate();
            return;
        }

        $form['FIELDS']   = json_decode($form['FIELDS_JSON'], true) ?? [];
        $form['SETTINGS'] = json_decode($form['SETTINGS_JSON'], true) ?? [];

        $this->arResult = [
            'FORM'   => $form,
            'SESSID' => bitrix_sessid(),
        ];

        $this->includeComponentTemplate();
    }
}

У template.php — ітерація по $arResult['FORM']['FIELDS'] з switch за типом поля.

Обробник сабміту

Універсальний обробник працює з будь-якою формою через FORM_ID:

// /local/ajax/form_builder_submit.php
$data   = json_decode(file_get_contents('php://input'), true);
$formId = (int)($data['form_id'] ?? 0);

$form = FormBuilderTable::getByPrimary($formId)->fetch();
if (!$form || !$form['IS_ACTIVE']) {
    echo json_encode(['error' => 'Form not found']);
    exit;
}

$fields   = json_decode($form['FIELDS_JSON'], true) ?? [];
$settings = json_decode($form['SETTINGS_JSON'], true) ?? [];

// Валідація обов'язкових полів
$errors = [];
foreach ($fields as $field) {
    if ($field['required'] && empty($data[$field['id']])) {
        $errors[$field['id']] = 'Поле обов\'язкове';
    }
}

if ($errors) {
    echo json_encode(['errors' => $errors]);
    exit;
}

// Зібрати дані для збереження
$submissionData = [];
foreach ($fields as $field) {
    $submissionData[$field['label']] = htmlspecialchars($data[$field['id']] ?? '');
}

// Зберегти результат
$subId = FormSubmissionTable::add([
    'FORM_ID'    => $formId,
    'DATA_JSON'  => json_encode($submissionData, JSON_UNESCAPED_UNICODE),
    'USER_IP'    => $_SERVER['REMOTE_ADDR'],
    'CREATED_AT' => new \Bitrix\Main\Type\DateTime(),
])->getId();

// CRM-інтеграція
if ($settings['crm_integration']['enabled'] ?? false) {
    // Знайти поля name/phone/email за типом
    $nameField  = $this->findFieldByType($fields, 'text');
    $phoneField = $this->findFieldByType($fields, 'tel');
    $emailField = $this->findFieldByType($fields, 'email');

    \Bitrix\Main\Loader::includeModule('crm');
    $lead = new \CCrmLead(false);
    $lead->Add([
        'TITLE'     => $form['TITLE'] . ': ' . ($data[$nameField['id']] ?? 'Новий лід'),
        'NAME'      => $data[$nameField['id']] ?? '',
        'PHONE'     => [['VALUE' => $data[$phoneField['id']] ?? '', 'VALUE_TYPE' => 'WORK']],
        'EMAIL'     => [['VALUE' => $data[$emailField['id']] ?? '', 'VALUE_TYPE' => 'WORK']],
        'SOURCE_ID' => 'WEB',
        'COMMENTS'  => json_encode($submissionData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT),
    ]);
}

echo json_encode(['success' => true]);

Терміни розробки

Варіант Склад Термін
Базовий конструктор Управління полями, збереження, рендер 8–12 днів
З CRM-інтеграцією + Ліди, маппінг полів, сповіщення 12–18 днів
Drag-and-drop + аналітика + Візуальний редактор, статистика форм 18–28 днів