Developing interactive forms with Vue.js for 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1173
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    745
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Developing Interactive Forms with Vue.js for 1C-Bitrix

Developing Interactive Forms with Vue.js for 1C-Bitrix

The standard bitrix:main.feedback component handles simple contact forms — name, phone, button. But as soon as you need a dynamic form with dependent fields, a multi-step scenario, real-time validation, or custom UI elements — the standard component falls short. A PHP template with page reload is no longer acceptable from a UX standpoint.

Vue.js combined with Bitrix solves this problem: the form operates as an SPA component on top of the PHP template, interacting with the server via AJAX.

Architecture of a Vue Form in Bitrix

A Vue.js form on a Bitrix site is built according to the following scheme:

  1. Mount point<div id="vue-form-app"></div> in the Bitrix component template.
  2. JS entry point — the Vue application mounts to this point. Data from PHP (component settings, field values, CSRF token) is passed via data-* attributes or a global JS object generated by PHP.
  3. API endpoint — the form handler is implemented as a PHP script or as a Bitrix REST handler (\Bitrix\Main\Engine\Controller). It accepts form data, validates server-side, and returns JSON.
  4. CSRF protectionbitrix_sessid() is passed to the form and verified on the server via check_bitrix_sessid().

Passing data from PHP to the Vue component:

// In the Bitrix component template
$APPLICATION->AddHeadScript('/local/js/dist/contact-form.js');
?>
<div id="contact-form-app"
     data-form-action="<?= htmlspecialchars($arResult['FORM_ACTION']) ?>"
     data-sessid="<?= bitrix_sessid() ?>"
     data-departments='<?= json_encode($arResult['DEPARTMENTS']) ?>'
></div>
// Vue component reads data on mount
const appEl = document.getElementById('contact-form-app');
const app = createApp(ContactForm, {
    formAction: appEl.dataset.formAction,
    sessid: appEl.dataset.sessid,
    departments: JSON.parse(appEl.dataset.departments),
});
app.mount(appEl);

When a Vue Form Is Justified

Vue for a form has higher development costs than the standard approach. It is justified in the following cases:

Dependent fields. "Select a region → select a city → select a pickup point" — three dependent fields loading data dynamically. With PHP and page reloads — poor UX.

Multi-step form (wizard). A loan application, service cost calculation, product configurator — multiple steps with data preserved between them. Vue is natural here: steps as components, data in a reactive store.

Real-time validation. Checking a tax ID for uniqueness, email availability, serial number validity — validation with a server request right as the user types, without waiting for form submission.

Calculator. A form-calculator where the result changes reactively as parameters change — delivery cost, materials cost, loan term.

Stack and Build Integration

The optimal Vue form stack for Bitrix projects:

  • Vue 3 (Composition API) + vite for bundling.
  • Vee-Validate or custom validation — field validation before submission.
  • Axios or native fetch — requests to the backend.
  • Built into a single bundle.js + bundle.css — included via $APPLICATION->AddHeadScript() in the Bitrix template.

Build system integration: for Bitrix projects, Vue form components are typically built separately from the main JS template using Vite with a build.lib configuration — an independent bundle that does not conflict with jQuery and other page scripts.

Server Side: Form Handler

The form handler in Bitrix is implemented in two ways:

Via \Bitrix\Main\Engine\Controller (preferred approach for D7 projects):

class ContactFormController extends \Bitrix\Main\Engine\Controller {
    public function submitAction(array $data): array {
        if (!\check_bitrix_sessid()) {
            return ['error' => 'Security error'];
        }
        // validation and saving
        return ['success' => true, 'message' => 'Request submitted'];
    }
}

The URL route is configured via routes.php or via the ajax parameter of the component.

Via a standalone AJAX handler — a simple PHP file in /local/ajax/ with a $_SERVER['HTTP_X_REQUESTED_WITH'] check. Less integrated, but simpler for quick implementation.

Case Study: Multi-step Window Configurator

Client — a PVC window manufacturer. Task: an online configurator letting users select window type, dimensions, hardware, color, and get a preliminary cost estimate right on the page.

Original version: a PHP form with page reload on each step. Conversion — low, users dropped off after the second step.

Implementation in Vue 3:

  • Step 1 — Window type: radio buttons with illustrations. The configuration preview updates reactively on selection.
  • Step 2 — Dimensions: numeric fields with range validation (min/max for each window type). "Non-standard size" hints when outside standard ranges.
  • Step 3 — Options: dependent lists: hardware and color depend on the selected profile. Data is loaded from the server when the profile changes.
  • Step 4 — Contact form: phone, email, preferred contact method. Configuration data + contacts sent to Bitrix24 CRM via REST API.

Cost was calculated reactively on the client using a formula whose parameters were passed from PHP during page initialization (prices from the Bitrix infoblock).

Result: conversion increased — users reached the final step significantly more often after seeing a real-time preliminary cost.

Timeframes

A simple Vue form with validation and AJAX submission — 3–5 days. A multi-step form with dependent fields and CRM integration — 10–20 days depending on the number of steps, validation complexity, and server-side requirements.

Standard Bitrix web forms (bitrix:main.feedback, bitrix:form.result.new) are reliable but rigid tools. They do not support conditional logic: showing field B only if value A is selected in field C. They cannot validate in real time before submission. They cannot operate in multi-step mode without page reload. For simple forms this is fine. For forms with business logic — it is not.

Vue.js here is not a trend — it is a solution to specific problems.

Architectural Approaches for Vue.js Integration with Bitrix

Integrating Vue.js into a Bitrix project is possible in several ways:

Embedding a Vue component into a Bitrix component template. The most common approach. A custom component template is created in which a Vue application is initialized. Data for the form (value lists, settings) is passed from PHP to JS via json_encode and global variables, or via data-* attributes.

// In the Bitrix component template:
<div id="vue-form-app"
     data-regions="<?= htmlspecialchars(json_encode($arResult['REGIONS'])) ?>"
     data-form-action="/local/ajax/form-handler.php">
</div>
<script src="/local/js/vue-form.js"></script>

Initialization via the Bitrix JS API. Bitrix has its own JS loading mechanism (\Bitrix\Main\Page\Asset::getInstance()->addJs()). The Vue component is registered as an extension and loaded through this mechanism — this is more correct from the perspective of caching and script load order.

REST API + Vue SPA. For fully standalone forms (quizzes, multi-step surveys) — the Vue application operates as an independent SPA, exchanging data with Bitrix via REST API or custom AJAX handlers.

Processing Form Data on the Server Side

The Vue form sends data to the server — who receives it?

Option 1: AJAX handler via bitrix:main.ajax. Create a PHP script that accepts a POST request, validates data, and works with the Bitrix API:

// /local/ajax/form-handler.php
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $data = json_decode(file_get_contents('php://input'), true);
    // Save to Bitrix web form:
    $eventFields = ['NAME' => $data['name'], 'EMAIL' => $data['email']];
    CFormResult::Add($formId, $eventFields);
    // or send a mail event:
    CEvent::Send('NEW_FORM_REQUEST', 's1', $eventFields);
}

Option 2: Bitrix REST API. For Bitrix24 — the standard REST. For on-premise Bitrix — a custom handler or a module with a REST controller (\Bitrix\Main\Engine\Controller).

Implementing Conditional Logic

The main advantage of Vue forms — reactive conditional logic:

// Vue 3 Composition API
const formData = reactive({
  serviceType: '',
  budget: '',
  region: ''
})

const showBudgetField = computed(() =>
  ['premium', 'enterprise'].includes(formData.serviceType)
)

const availableRegions = computed(() =>
  formData.serviceType === 'local' ? localRegions : allRegions
)

Such logic is not feasible in a standard Bitrix PHP template without significant effort. Vue handles it declaratively.

Validation and UX

For validation, use vee-validate or manually written validation with the Composition API. Principles:

  • Inline validation — the error is shown immediately when the field loses focus, without waiting for submission.
  • Server-side validation — after submission, the server can return errors that are displayed in the appropriate fields.
  • Disabled button state — while the form is invalid, the submit button is visually disabled.

Case Study: Multi-step Service Selection Quiz

Client — a web studio. A quiz was needed on the landing page: 5 steps with questions, each next step dependent on the answer to the previous one. At the end — a personalized result and a contact form. The outcome — a lead in Bitrix24 CRM via REST.

This is not achievable with standard Bitrix tools. Third-party SaaS quizzes — not an option (CRM integration and custom design are required).

Solution: Vue 3 SPA embedded in the landing page template.

Component structure:

  • QuizStep.vue — reusable step component with different question types (single choice, multiple choice, slider)
  • QuizResult.vue — personalized result based on answers
  • ContactForm.vue — final form with validation

Step routing logic — computed property based on answers. Quiz data was saved in localStorage — the user could refresh the page and continue from the same step.

After completion — POST to the Bitrix24 REST API creating a lead (crm.lead.add) with fields from quiz answers. The responsible person was assigned automatically via a business process.

Quiz conversion (started → reached contact form) — 67%. Conversion of the simple form on the same page before implementation — 12%.

Build and Deploy

Vue components for Bitrix projects are built via Vite or Webpack. The built bundle (form.js, form.css) is placed in /local/js/ or /local/css/ and included via the template or via \Bitrix\Main\Page\Asset.

In vite.config.jsbuild.lib or build.rollupOptions.output for generating a bundle without chunk splitting, if the component is embedded in a Bitrix page (not SPA).

Timeframes

Developing one interactive form with conditional logic and Bitrix integration (CRM or web form) — 5–10 working days. A multi-step quiz with personalized results and REST integration — 10–20 working days.