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

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Wizard
Сообщения: 169
Зарегистрирован: 2018.02.05, 13:41
Контактная информация:

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

Сообщение Wizard » 2018.03.01, 20:42

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

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

kapkapiton
Сообщения: 26
Зарегистрирован: 2018.01.30, 11:04
Контактная информация:

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

Сообщение kapkapiton » 2018.03.01, 20:50

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 в этом случае

Wizard
Сообщения: 169
Зарегистрирован: 2018.02.05, 13:41
Контактная информация:

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

Сообщение Wizard » 2018.03.02, 15:32

Вообщем танцы с бубном привели меня к выводу что 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'});
                // ...
            }
       }
или еще лучше - указать в настройках формы 'мультиполя' и что бы правила прописывались не к каждому полю а для группы полей

andku83
Сообщения: 988
Зарегистрирован: 2016.07.01, 10:24
Откуда: Харьков

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

Сообщение andku83 » 2018.03.02, 15:57


Wizard
Сообщения: 169
Зарегистрирован: 2018.02.05, 13:41
Контактная информация:

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

Сообщение Wizard » 2018.03.02, 16:22

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

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

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

Wizard
Сообщения: 169
Зарегистрирован: 2018.02.05, 13:41
Контактная информация:

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

Сообщение Wizard » 2018.03.02, 17:00

Ну вообщем все получилось!)) Спасибо еще раз 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;
    
});

");

Ответить