【问题标题】:Bind dynamically generated forms for ajax validation?绑定动态生成的表单以进行 ajax 验证?
【发布时间】:2017-06-06 22:57:47
【问题描述】:

我正在使用 JS 在页面上动态生成许多表单。

每个表单对应一个 yii2 模型(它为每个属性设置了规则)。

我希望每个表单都验证所有元素(姓名、电子邮件文本输入)以使用 ajax 进行验证(就像他们通常会做的那样,就好像我只有一个表单一样)。

我发现使用这里指出的方法: https://yii2-cookbook.readthedocs.io/forms-activeform-js/

`$('#contact-form').yiiActiveForm('validateAttribute', 'contactform-name');`

给出 JS 错误:

 yii.activeForm.js:276 Uncaught TypeError: Cannot read property 'attributes' of undefined
    at jQuery.fn.init.find (yii.activeForm.js:276)
    at jQuery.fn.init.validateAttribute (yii.activeForm.js:268)
    at jQuery.fn.init.$.fn.yiiActiveForm (yii.activeForm.js:16)
    at HTMLInputElement.<anonymous> (search-follow.js:130)

有没有办法将动态生成的表单绑定到 yii2 验证? (不仅仅是单个字段,而是整个表单,每个表单都有一个唯一的 ID)。

不幸的是,Yii2 js 表单验证的文档似乎没有那么多

非常感谢帮助

g

【问题讨论】:

    标签: jquery forms yii2


    【解决方案1】:

    简而言之,您可以通过以下步骤利用原生 gii 生成的活动表单来完成模态验证:

    在位置创建文件app/web/js/ajax-modal-popup.js

    $(function(){
         $(document).on('click', '.showModalButton', function(){
            if ($('#modal').data('bs.modal').isShown) {
                $('#modal').find('#modalContent')
                    .load($(this).attr('value'));
                document.getElementById('modalHeader').innerHTML = '<h4>' + $(this).attr('title') + '</h4>';
            } else {
                $('#modal').modal('show')
                    .find('#modalContent')
                    .load($(this).attr('value'));
                document.getElementById('modalHeader').innerHTML = '<h4>' + $(this).attr('title') + '</h4>';
            }
        });
    });
    

    在位置更新文件app/asset/AppAsset.php

    class AppAsset extends AssetBundle {
    
        public $basePath = '@webroot';
        public $baseUrl = '@web';
        public $css = [
        ];
        public $js = [
            'js/ajax-modal-popup.js', //<<<------- Register the script.
        ];
        public $depends = [
            'yii\web\YiiAsset',
        ];
    
    }
    

    将代码块添加到文件位置app/views/index.php

    <?php
        Html::button('Close', 
          ['value' => Url::to(['ticket/close', 'id'=>$model->ticket_id]), 
          'class' => 'showModalButton btn btn-success']
        );
    
        Modal::begin([
            'header' => '<h2>Ticket Manager</h2>',
            'id' => 'modal',
            'size' => 'modal-md',
        ]);
        echo "<div id='modalContent'></div>";
        Modal::end();
    ?>
    

    添加到控制器app/controllers/ticketController.php

    public function actionClose($id) {
        $model = $this->findModel($id);
        $model->scenario = 'close'; //Applied by Ticket model rules.
        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            $model->record_void = 1;
            $model->save();
            return $this->redirect(['index']);
        }elseif (Yii::$app->request->isAjax) {
            return $this->renderAjax('close', [
                'model' => $model
            ]);
        } else {
            return $this->render('close', [
                'model' => $model
            ]);
        }
    }
    

    您的表单文件位置app/views/ticket/close.php

    <?php
    
    use yii\helpers\Html;
    use yii\widgets\ActiveForm;
    
    /* @var $this yii\web\View */
    /* @var $model app\models\Ticket */
    /* @var $form ActiveForm */
    ?>
    <div class="ticket-_close">
    <h3>Close Ticket</h3>
    <?php
        $form = ActiveForm::begin(['options' => [
            'id' => 'takeModal',
            'enableClientValidation' => true,
            'enableAjaxValidation' => true,
        ]]);?>
    
            <?= $form->field($model, 'ticket_id')->textInput(['readonly' => true, 'value' => $model->ticket_id]) ?>
            <?= $form->field($model, 'problem') ?>
            <?= $form->field($model, 'solution') ?>
    
            <div class="form-group">
                <?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
            </div>
        <?php ActiveForm::end(); ?>
    
    </div><!-- ticket-_close -->
    

    有关更多详细信息,请参阅下面的文章。

    http://www.yiiframework.com/wiki/806/render-form-in-popup-via-ajax-create-and-update-with-ajax-validation-also-load-any-page-via-ajax-yii-2-0-2-3/

    【讨论】:

    • 感谢 Jairus,但这并没有说明如何将 js 生成的表单绑定到 Yii2 JS 验证。表单 ID 的生成(在 JS 中)如下:id="form-1"、id="form-2" 等这些
      中的每一个都需要以某种方式与 yiiActiveForm JS 绑定
    • 我在顶部添加了一个示例,这是您要找的吗?上面的解决方案现在允许您添加与表单一样多的按钮。然后动态加载表单并像进入表单页面一样工作。现在它将使用 ajax 进行验证,因为 @egulhan 指出您需要在 activeForm 上设置 enableAjaxValidation 参数。
    • 我认为解决方案需要基于 JS。不确定 Yii 是否允许对多个表单(指向相同的模型验证器)进行 ajax 验证。我找不到任何文件表明它可以。像 yiiActiveForm.bind('form-id1') 这样的东西会很棒......
    • 所以这使用了ActiveForm小部件生成的所有本机JS。也许我错过了你想要做的事情。您能否上传一些代码并描述您的应用程序?
    • 不,JS不是activeForm widget生成的,需要被它绑定。我不确定如何比上面更好地解释它。我现在已经完成了手动 JS 验证(ajax),所以让它工作了,但是,如果能够做到这一点而不需要重新发明轮子以在表单上显示错误(yiiActiveForm 已经有所有这些东西的方法),那就太好了。
    【解决方案2】:

    我很快放了一些代码 sn-ps,它们使用 Yii 2 进行 ajax 表单操作。

    查看(_ajaxForm.php:ajax表单)

    <?php $form = \yii\widgets\ActiveForm::begin([
        // pay attention this config.
        'id' => 'account-form',
        'enableClientValidation' => true,
        'enableAjaxValidation' => true,
        // validation URL via ajax
        'validationUrl' => \yii\helpers\Url::to(['/account/do-ajax-request', 'userId'=>$model->id, 'op' => 'validate-form']),
    ]); ?>
    
    <?= $form->field($model, 'email')->textInput(['maxlength' => true]) ?>
    
    <?= $form->field($model, 'password')->passwordInput(['maxlength' => true]) ?>
    
    <?= $form->field($model, 'passwordConfirm')->passwordInput(['maxlength' => true]) ?>
    
    <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
    
    <div class="form-group">
        <?= \yii\helpers\Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
    </div>
    
    <?php \yii\widgets\ActiveForm::end(); ?>
    
    <script type="text/javascript">
        $(function () {
            // URL to save form via ajax
            var formSaveUrl='<?= \yii\helpers\Url::to(['/account/do-ajax-request', 'userId'=>$model->id, 'op' => 'save-form']) ?>';
    
            // post form via ajax to save
            $(document).on('beforeSubmit', '#account-form', function () {
                $.post(formSaveUrl, $(this).serialize(), function (data) {
                    alert(data.message);
                });
                return false;
            });
    
        });
    </script>
    

    控制器(AccountController.php:执行ajax操作的函数)

    public function actionDoAjaxRequest($userId, $op)
    {
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
    
        $model = $this->findModel($userId);
        $model->load(Yii::$app->request->post());
    
        // validate form
        if ($op == 'validate-form') {
            $data = \yii\widgets\ActiveForm::validate($model);
        // save form
        } else if ($op == 'save-form') {
            if ($model->save()) {
                $data['result'] = true;
                $data['message'] = 'Success!';
            } else {
                $data['result'] = false;
                $data['message'] = 'Failed!';
            }
        }
    
        return $data;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-08
      • 1970-01-01
      相关资源
      最近更新 更多