Сейчас узнаем, какой подарок выпадет именно Вам
Крутите колесо
Как сделать сложный калькулятор в ZeroBlock в Tilda
1
Тип помещения
2
Тип уборки
3
Площадь для уборки, м²
4
Количество с/у
5
Площадь ковров, м.кв
6
Дополнительные услуги
6*
Дополнительные услуги
7
Животные
8
Файл
9
Ночная уборка
10
Комментарии
11
Контактные данные
Стоимость уборки:
Заказать уборку
* Данный расчет является предварительным, детальную стоимость уточняйте у менеджеров компании
Mo-ti Level Up
Видео инструкции по добавлению кода и работе с Zero Block.
Делаем сложный калькулятор в ZeroBlock со свободным позиционированием элементов

Фрагмент видео

Как сделать сложный калькулятор в ZeroBlock в Tilda

1
Создали ZeroBlock и добавили в него несколько элементов Form и один элемент Button ( с классом sendform)
2
Выбрали основную форму (в примере это Телефон, ФИО, Адрес) и задали ей класс mainform
3
Остальным формам в блоке задали класс slaveform
И прописали data атрибуты с индексами 1,2,3,4.... для каждой формы, чтобы сформировать порядок полей в корзине
4
Формулу для калькулятора задана обычной линейной функцией
5
Добавили скрипт на страницу
Скрипт вставляется в блок Другое - Т123
Библиотека для примера
<style>
.sendform {cursor:pointer}
.mainform .hide-input-mode {
    opacity: 0;
    height: 0;
    max-height: 0;
    min-height: 0;
    pointer-events: none;
    overflow: hidden;
    position: absolute;
    z-index: -10;
}

.slaveform .t-submit {
    display: none !important;
}

</style>

<script>
document.addEventListener('DOMContentLoaded', function() {
    document.addEventListener('click', function(event) {
        const sendButton = event.target.closest('.sendform');
        if (!sendButton) return;
        
        const tRec = sendButton.closest('.t-rec');
        if (!tRec) return;
        
        const allErrorControls = tRec.querySelectorAll('.t-input-group.js-error-control-box');
        allErrorControls.forEach(element => {
            element.classList.remove('js-error-control-box');
        });
        
        const slaveForms = tRec.querySelectorAll('.slaveform');
        const mainForm = tRec.querySelector('.mainform');
        
        if (slaveForms.length === 0 || !mainForm) return;
        
        const sortedSlaveForms = Array.from(slaveForms).sort((a, b) => {
            const posA = parseInt(a.getAttribute('data-position')) || 0;
            const posB = parseInt(b.getAttribute('data-position')) || 0;
            return posA - posB;
        });
        
        const inputsBox = mainForm.querySelector('.t-form__inputsbox');
        if (!inputsBox) return;

        const oldHideInputs = inputsBox.querySelectorAll('.hide-input-mode');
        oldHideInputs.forEach(element => {
            element.remove();
        });
        
        let insertAfterElement = null;
        
        sortedSlaveForms.forEach((slaveForm) => {
            const position = slaveForm.getAttribute('data-position') || 'не указан';
            const slaveInputsBox = slaveForm.querySelector('.t-form__inputsbox');
            if (!slaveInputsBox) return;

            const children = slaveInputsBox.children;
            
            for (let i = 0; i < children.length; i++) {
                const child = children[i];
                
              
                const isInputGroup = child.classList.contains('t-input-group');
                const isHiddenInput = child.tagName === 'INPUT' && 
                                     child.type === 'hidden' && 
                                     child.getAttribute('tabindex') === '-1';
                
                let shouldClone = false;
                
                if (isInputGroup) {
       
                    const ariaHidden = child.getAttribute('aria-hidden');
                    if (!ariaHidden || ariaHidden === 'false') {
                        shouldClone = true;
                    }
                } else if (isHiddenInput) {
                    shouldClone = true;
                }
                
                if (shouldClone) {
                    const clone = child.cloneNode(true);
                    clone.classList.add('hide-input-mode');
                    clone.dataset.sourcePosition = position;
                    clone.dataset.sourceIndex = i;
                    
          
                    const originalSelect = child.querySelector('select');
                    const clonedSelect = clone.querySelector('select');
                    if (originalSelect && clonedSelect) {
                        clonedSelect.value = originalSelect.value;
                    }
                    
     
                    if (insertAfterElement) {
                        insertAfterElement.parentNode.insertBefore(clone, insertAfterElement.nextSibling);
                        insertAfterElement = clone;
                    } else {
                        inputsBox.insertBefore(clone, inputsBox.firstChild);
                        insertAfterElement = clone;
                    }
                }
            }
        });
        
        setTimeout(() => {
            const submitButton = mainForm.querySelector('.t-submit');
            if (submitButton) {
                submitButton.click();
            }
            
            setTimeout(() => {
                const errorElements = mainForm.querySelectorAll('.hide-input-mode.js-error-control-box');
                
                if (errorElements.length > 0) {
         
                    const hideInputsToRemove = mainForm.querySelectorAll('.hide-input-mode');
                    hideInputsToRemove.forEach(element => {
                        element.remove();
                    });
                    
                    const firstErrorElement = errorElements[0];
                    let targetSlaveForm = null;
                    
                    sortedSlaveForms.forEach(slaveForm => {
                        if (slaveForm.contains(firstErrorElement)) {
                            targetSlaveForm = slaveForm;
                        }
                    });
                    
                    if (!targetSlaveForm) {
                        const errorSourcePosition = firstErrorElement.dataset.sourcePosition;
                        if (errorSourcePosition) {
                            sortedSlaveForms.forEach(slaveForm => {
                                const position = slaveForm.getAttribute('data-position');
                                if (position === errorSourcePosition) {
                                    targetSlaveForm = slaveForm;
                                }
                            });
                        }
                    }
                    
                    if (targetSlaveForm) {
                        const slaveSubmit = targetSlaveForm.querySelector('.t-submit');
                        if (slaveSubmit) {
                            slaveSubmit.click();
                        }
                    }
                }
                
            }, 200);
            
        }, 200);
        
    });
});

function t396_onSuccess(form) {
    let formElement = form;
    if (form instanceof jQuery) {
        formElement = form.get(0);
    }
    if (typeof form === 'string') {
        formElement = document.querySelector(form);
    }
    if (!formElement || typeof formElement.querySelectorAll !== 'function') return;
    
    const mainForm = formElement.closest('.mainform');
    if (!mainForm) return;

    const hideInputs = mainForm.querySelectorAll('.hide-input-mode');
    hideInputs.forEach(element => {
        element.remove();
    });
    
    const tRec = mainForm.closest('.t-rec');
    if (tRec) {
        const errorControls = tRec.querySelectorAll('.t-input-group.js-error-control-box');
        errorControls.forEach(element => {
            element.classList.remove('js-error-control-box');
        });
        
        const slaveForms = tRec.querySelectorAll('.slaveform');
        slaveForms.forEach(slaveForm => {
            const formElementInSlave = slaveForm.querySelector('form');
            if (formElementInSlave && window.t_forms__clearForm) {
                window.t_forms__clearForm(formElementInSlave);
            }
        });
    }
}
</script>
Стили из этого примера
<style>
.slaveform .t-img-select__indicator,
.main .t-img-select__indicator {
    border: none;
}

label.t-img-select__control {
    border: 3px solid #eee;
    border-radius: 10px;
    overflow: hidden;
    cursor: pointer;
    transition: border-color .2s, transform .15s;
    background: #fff;
    text-align: center;
}

.t-img-select__indicator.t-bgimg {
    background-size: 80%;
    background-repeat: no-repeat;
    background-position: center;
    background-color: #FFF7ED !important;
}

label.t-img-select__control:hover {
    border-color: #FFB347;
    transform: translateY(-1px);
}

label.t-img-select__control:has(.t-img-select:checked) {
    border-color: #FFB347;    
}


.t-img-select__text {
    margin-bottom: 12px;
}


.t-img-select__indicator:after {
    top: 5px;
    left: auto;
    right: 5px;
}


span.t-calc__postfix-text {
    color: #d7d7d7;
    font-size: 28px;
}

.t-upwidget-container__button {
    background-image: linear-gradient(0.375turn,rgba(255,179,71,1) 0%,rgba(255,140,0,1) 50%,rgba(255,106,0,1) 100%);
}

    
</style>
Made on
Tilda