Страница 1 из 1

Js валидация динамических полей формы

Добавлено: 2018.03.01, 20:42
BalykhinAS
Наткнулся на очень не приятный момент, вероятно всего не разобрался, но не нашел штатных инструментов для валидации динамических полей. Собственно потребность то не редкая - по клику на кнопку добавить несколько телефонов, адресов доставки, вариантов опций характеристик, вообщем примеров множество. Использовать отдельные экшены (по крайней мере не для мелочей) или ajax не вариант!

Если кто решал данные задачи самостоятельно дайте наводку!

Re: Js валидация динамических полей формы

Добавлено: 2018.03.01, 20:50
kapkapiton
https://yii2-cookbook.readthedocs.io/fo ... veform-js/ я решал таким способом.

Добавление валидации.

Код: Выделить всё

$('#contact-form').yiiActiveForm('add', {
    id: 'address',
    name: 'address',
    container: '.field-address',
    input: '#address',
    error: '.help-block',
    validate:  function (attribute, value, messages, deferred, $form) {
        yii.validation.required(value, messages, {message: "Validation Message Here"});
    }
});

Только мне такой способ не очень нравится, хотелось бы использовать rules модели, в соседней ветке задал вопрос. Возможно не до конца разобрался в документации и там просто нужно использовать ajax в этом случае

Re: Js валидация динамических полей формы

Добавлено: 2018.03.02, 15:32
BalykhinAS
Вообщем танцы с бубном привели меня к выводу что ActiveForm совсем не заточен для динамических полей формы :D

Код: Выделить всё

<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;

?>

    <?php $form = ActiveForm::begin(); ?>

    <h3>Товар</h3><br/>

    <?= $form->field($model->product, 'name')->textInput()->label('Название') ?>
    <?= $form->field($model->product, 'description')->textarea()->label('Описание') ?>

    <br/><h3>Варианты</h3><br/>

    <div class="productVariants">
        <div class="row">
            <div class="col-xs-4">
                <?= Html::label('Название', '', ['class' => 'control-label']) ?>
            </div>
            <div class="col-xs-3">
                <?= Html::label('Артикул', '', ['class' => 'control-label']) ?>
            </div>
            <div class="col-xs-2">
                <?= Html::label('Цена', '', ['class' => 'control-label']) ?>
            </div>
            <div class="col-xs-2">
                <?= Html::label('Наличие', '', ['class' => 'control-label']) ?>
            </div>
            <div class="col-xs-1">
                <?= Html::label('&nbsp;', '', ['class' => 'control-label']) ?>
            </div>
        </div>
        <div class="productVariantsBody">
        <?php foreach($model->variants as $i => $variant): ?>
        <div class="row productVariant" style="margin-bottom: 10px;">
            <div class="col-xs-4">
                <?= Html::hiddenInput($model->variants[0]->formName() . '['.$i.'][id]', $variant->id) ?>
                <?= $form->field($variant, '['.$i.']name')->label(false) ?>
            </div>
            <div class="col-xs-3">
                <?= $form->field($variant, '['.$i.']sku')->label(false) ?>
            </div>
            <div class="col-xs-2">
                <?= $form->field($variant, '['.$i.']price')->label(false) ?>
            </div>
            <div class="col-xs-2">
                <?= $form->field($variant, '['.$i.']stock')->label(false) ?>
            </div>
            <div class="col-xs-1">
                <?= Html::button('Удалить', ['class' => 'btn btn-danger removeVariant']) ?>
            </div>
        </div>
        <?php endforeach; ?>
        </div>
    </div>

    <div class="form-group">
        <?= Html::button('Добавить вариант', ['class' => 'btn btn-warning addVariant']) ?>
        <?= Html::submitButton('Сохранить', ['class' => 'btn btn-success']) ?>
    </div>

    <?php ActiveForm::end(); ?>

<?php

$this->registerJs("

$(document).on('click', '.removeVariant', function() { $(this).closest('.row').remove() });

var regexID   = /(\w+?)(-\d-{1,}|--\d{1,}-)/;
var regexName = /(\w+)(\[\d{1,}\]|\[-\d{1,}\])/;

var variantIndex = -1;
var variantTemplate = $('.productVariant:last').clone(false);

$('.addVariant').on('click', function() { 
    $(variantTemplate).clone(false).appendTo('.productVariantsBody');
    $('.productVariant:last').html(
        $('.productVariant:last').html()
            .replace(new RegExp(regexName,'gi'), '$1['+ variantIndex +']')
            .replace(new RegExp(regexID,'gi'), '$1-'+ variantIndex +'-')
    );
    $('.productVariant:last input').each(function(i,e) {
        $(e).val('');
	addValidator(e);
    });
    variantIndex = variantIndex-1;
});

function addValidator(field) {

    // тут добавляем некое условие что бы понять есть ли у данного поля валидаторы
    // адскими усилиями можно достать их по примеру ActiveForm
    
    if( условие ){
        $(field).closest('form').yiiActiveForm('add', {
            id: $(field).attr('id'),
            name: $(field).attr('name'),
            container: $(field).parent(),
            input: $(field),
            error: $(field).parent().find('.help-block'),
            validate:  function (attribute, value, messages, deferred, $form) {
                yii.validation.required(value, messages, {message: 'Validation Message Here'});
                // ...
            }
        });
    }
}

");
?>
сама функция крайне бессмысленная)))

Код: Выделить всё

        
        $(field).closest('form').yiiActiveForm('add', {
            id: $(field).attr('id'),
            name: $(field).attr('name'),
            container: $(field).parent(),
            input: $(field),
            error: $(field).parent().find('.help-block'),
            validate:  function (attribute, value, messages, deferred, $form) {
                yii.validation.required(value, messages, {message: 'Validation Message Here'});
                // ...
            }
        });
было бы куда проще если бы ею можно было воспользоваться как то так

Код: Выделить всё

	$('input[name*=VariantForn][name*=name]').yiiActiveForm('add', {
            validate:  function (attribute, value, messages, deferred, $form) {
                yii.validation.required(value, messages, {message: 'Validation Message Here'});
                // ...
            }
       }
или еще лучше - указать в настройках формы 'мультиполя' и что бы правила прописывались не к каждому полю а для группы полей

Re: Js валидация динамических полей формы

Добавлено: 2018.03.02, 15:57
andku83

Re: Js валидация динамических полей формы

Добавлено: 2018.03.02, 16:22
BalykhinAS
shnir писал(а): 2018.03.02, 15:57 https://github.com/unclead/yii2-multipl ... le-columns поизучайте
заглянул, спасибо!

смотрел подобные работы - ад))) судя по всему это надо принять - без таких вот костылей не обойтись)

но действительно нашел полезную вещь!!! Спасибо!

Re: Js валидация динамических полей формы

Добавлено: 2018.03.02, 17:00
BalykhinAS
Ну вообщем все получилось!)) Спасибо еще раз shnir, по ссылке подсмотрел реализацию javascript

достаточно было собрать все поля объекте yiiActiveForm

Код: Выделить всё

    var attributes = [];
    $('.productVariant:last input').each(function(i, e) {
        var attribute = $(e).closest('form').yiiActiveForm('find', $(e).attr('id'));
        attributes[i] = attribute;
    });
и подставить в новый ряд

Код: Выделить всё

    $('.productVariant:last input').each(function(i,field) {
        $(field).val('');
        $(field).closest('form').yiiActiveForm('add', $.extend({}, attributes[i], {
                'id': $(field).attr('id'),
                'input': $(field),
                'container': $(field).parent()
        }));
    });
все валидируется, круть! конечно код обрастет условиями и проверками, но для частного случая в поле достаточно

Код: Выделить всё

$this->registerJs("

$(document).on('click', '.removeVariant', function() { $(this).closest('.row').remove() });

var regexID   = /(\w+?)(-\d-{1,}|--\d{1,}-)/;
var regexName = /(\w+)(\[\d{1,}\]|\[-\d{1,}\])/;

var variantIndex = -1;
var variantTemplate = $('.productVariant:last').clone(false);

$('.addVariant').on('click', function() { 

    $(variantTemplate).clone(false).appendTo('.productVariantsBody');
    
    var attributes = [];
    $('.productVariant:last input').each(function(i, e) {
        attributes[i] = $(e).closest('form').yiiActiveForm('find', $(e).attr('id'));
    });

    $('.productVariant:last').html(
        $('.productVariant:last').html()
            .replace(new RegExp(regexName,'gi'), '$1['+ variantIndex +']')
            .replace(new RegExp(regexID,'gi'), '$1-'+ variantIndex +'-')
    );
    
    $('.productVariant:last input').each(function(i,field) {
        $(field).val('');
        $(field).closest('form').yiiActiveForm('add', $.extend({}, attributes[i], {
                'id': $(field).attr('id'),
                'input': $(field),
                'container': $(field).parent()
        }));
    });
    
    variantIndex = variantIndex-1;
    
});

");