美文网首页
Yii2的表单验证之三:Ajax验证

Yii2的表单验证之三:Ajax验证

作者: 沪江快速手机打字 | 来源:发表于2017-05-27 17:48 被阅读0次

Yii2具有强大的表单验证功能,能用好表单验证,用户输入就基本掌握了,在这里我和各位聊聊Yii2的Ajax验证器

实际上,Yii2并没有Ajax验证器这个概念,只是为了便于描述使用Ajax方式进行的数据验证,我在这里单独提出的一个说法而已!

所谓的Ajax验证器,就是当enableAjaxValidation==true时在request->isAjax代码块中执行的验证器。

Ajax验证代码结构大概是这样:

if (Yii::$app->request->isAjax) {
    Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
    $result = \yii\bootstrap\ActiveForm::validate($model);
    return $result;
}

这段代码通常存在于服务器端验证器(即$model->validate())之前,请参考后面的源码。

Ajax验证实际上就是由客户端触发,使用Ajax技术进行的服务器端验证,验证结果以客户端页面的局部刷新的方式展现出来,因Ajax验证良好的用户体验而被广泛使用。

先来看看Ajax验证是什么样的效果?

21.jpg
上图红框中就是Ajax验证的结果,在国家名称中输入了“France”,在其失去焦点(鼠标在页面空白的地方点击一下)后,输入框变为了红色,其下方也出现了错误提示信息。需要注意的是:这个错误提示信息是由服务器端验证后发送过来的动态结果,这与客户端验证器是不同的。
从上图右边的表格你也可以看到“France”这个国家在数据库中是已经存在的!
22.jpg
上图中在国家名称中输入了“Egypt”,在其失去焦点后,输入框变为了绿色,即Ajax验证通过。

Ajax验证器的定义

类似的,Ajax验证器与服务器端验证器、客户端验证器定义方式都是一样的——在rules()中定义:
public function rules() {
return [
[['countryName','countryAbbr','continent'], 'required'],
['continent','default','value'=>'Asia'],
//Ajax验证器,对'countryName'进行唯一性(unique)检测
[['countryName'], 'unique',
//Ajax验证要使用的AR(Active Record)类
'targetClass' => '\frontend\models\Country',
//Ajax验证时,'countryName'输入项对应于'name'字段进行验证(即对Country表中的'name'字段进行查询)
'targetAttribute' => ['countryName'=>'name']
],
[['countryAbbr'], 'unique','targetClass' => '\frontend\models\Country', 'targetAttribute' => ['countryAbbr'=>'code']],
];
}

要使上例代码中countryName验证规则成为真正的Ajax验证器,还需要在视图文件中对enableAjaxValidation进行设置。

在视图文件中对enableAjaxValidation进行设置有两个可选位置:
1、在ActiveField中对单项field进行设置
2、在ActiveForm中对整个表单进行设置
在此推荐第1种方法,即哪个表单项field需要Ajax验证时,就将它的enableAjaxValidation设置为true,这样避免触发不必要的Ajax请求,示例代码如下:

<?=$form->field($model,'countryName',['enableAjaxValidation'=>true])->textInput()?>

在Yii2中,ActiveFormenableAjaxValidation默认值是false,即整个表单的Ajax验证失效,但此时是可以针对field开启单项的Ajax验证的。

if (Yii::$app->request->isAjax) {
    Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
    $result = \yii\bootstrap\ActiveForm::validate($model);
    return $result;
}

最后就是在ControllerAction中将上面这段代码添加到$model->validate()之前(请参考后面的源码),你的Ajax验证器就正式生效了!

本文所涉及到的程序源码

文件位置:D:\phpwork\advanced\frontend\controllers\DemoController.php

<?php
namespace frontend\controllers;
use Yii;
class DemoController extends CommonController{
     public function actionForm3() {
        $model=new \frontend\models\Form3();
        if ($model->load(Yii::$app->request->post())) {
            //是Ajax请求时才执行验证
            if (Yii::$app->request->isAjax) {
                //使用ActiveForm的validate()方法对$model的数据进行验证
                $result=\yii\bootstrap\ActiveForm::validate($model);
                Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;//设置返回客户端的结果使用json格式
                //将验证结果返回客户端
                return $result;
            }
            if($model->validate()){
                if ($model->save()) {
                    return $this->render('form3a',['model'=>$model]);
                }else{
                    return $this->error('Sorry,Data save fail!');
                }
            }else{
                return $this->errorDisplay($model->getErrors());
            }
        }else{
            $countries=\frontend\models\Country::find()->asArray()->all();
            return $this->render('form3',['model'=>$model,'countries'=>$countries]);
        }
    }
}

其中errorDisplay()方法是调用自CommonController,请参见:
http://www.jianshu.com/p/5d2c42166702

文件位置:D:\phpwork\advanced\frontend\models\Form3.php

<?php
namespace frontend\models;
use Yii;
class Form3 extends \yii\base\Model{
    public $countryName,$countryAbbr,$continent;
    public function attributeLabels() {
        return [
            'countryName'=>'国家名称',
            'countryAbbr'=>'简称',
            'continent'=>'大洲',
        ];
    }
    public function rules() {
        return [
            [['countryName','countryAbbr','continent'], 'trim'],
            [['countryName','countryAbbr','continent'], 'required'],
            ['continent','default','value'=>'Asia'],
            //Ajax验证器,对'countryName'进行唯一性(unique)检测
            [['countryName'], 'unique',
                //Ajax验证要使用的AR(Active Record)类
                'targetClass' => '\frontend\models\Country',
                //Ajax验证时,'countryName'输入项对应于'name'字段进行验证(即对Country表中的'name'字段进行查询)
                'targetAttribute' => ['countryName'=>'name']
            ],
            [['countryAbbr'], 'unique','targetClass' => '\frontend\models\Country', 'targetAttribute' => ['countryAbbr'=>'code']],
        ];
    }
    public function save() {
        return true;
    }
}

文件位置:D:\phpwork\advanced\frontend\views\demo\form3.php

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

?>
    <div class="panel panel-warning">
        <div class="panel-heading">
            <div class="panel-title">
                三、Yii2的表单验证——Ajax验证的验证器
            </div>
        </div>
        <div class="panel-body">
            <div class="row">
                <div class="col-md-7">
                    <?php
                    $form = ActiveForm::begin([
//                        'enableClientValidation' => false,
                        'enableClientValidation' => true,
//                        'enableAjaxValidation'=>true,//从性能考虑,避免将整个表单设置为Ajax验证
                        'enableAjaxValidation'=>false,//ActiveForm默认此值即为false,即整个表单的Ajax验证失效
                        'layout' => 'horizontal',
                    ]);
                    ?>
                    <!-- 对'countryName'进行Ajax验证,设置其enableAjaxValidation为true -->
                    <?=$form->field($model,'countryName',['enableAjaxValidation'=>true])->textInput()?>
                    <!-- 对'countryAbbr'进行Ajax验证,设置其enableAjaxValidation为true -->
                    <?=$form->field($model,'countryAbbr',['enableAjaxValidation'=>true])->textInput()?>
                    <?=$form->field($model,'continent')->textInput()?>
                    <div class="row">
                        <div class='col-md-2 col-md-offset-2'><?= Html::submitButton('提     交 ', ['class' => 'btn btn-primary form-control']) ?></div>
                        <div class='col-md-2 col-md-offset-2'><?= Html::resetButton('重     置 ', ['class' => 'btn btn-default form-control'])?></div>
                    </div>
                    <?php ActiveForm::end(); ?>
                </div>
                <div class="col-md-5">
                    <TABLE class="table table-bordered country">
                        <TR >
                            <TD style="width:60px;">序号</TD>
                            <TD>国家</TD>
                            <TD style="width:60px;">简称</TD>
                            <TD>大洲</TD>
                        </TR>
                        <?php
                        foreach ($countries as $k=>$item) {
                            echo '<TR><TD>'.($k+1).'</TD><TD>'.$item['name'].'</TD><TD>'.$item['code'].'</TD><TD>'.$item['continent'].'</TD></TR>';
                        }
                        ?>
                    </TABLE>
                </div>
            </div>
        </div>
    </div>

文件位置:D:\phpwork\advanced\frontend\views\demo\form3a.php

<?php
use yii\widgets\DetailView;
?>
    <div class="panel panel-warning">
        <div class="panel-heading">
            <div class="panel-title">
                三、Yii2的表单验证——Ajax验证的验证器(提交数据的显示)
            </div>
        </div>
        <div class="panel-body" style="height:500px;">
            <?php
            echo DetailView::widget([
                'model' => $model,
                'attributes' => [
                    'countryName',
                    'countryAbbr',
                    'continent',
                ],
                'template' => '<tr><th class="text-right" style="width:150px;">{label}</th><td>{value}</td></tr>',
            ]);
            ?>
            <button onclick="history.back()" class="btn btn-default">返 回</button>
        </div>
    </div>

Country类是Yii2官网实例中的一个类,请参照官网文档自行构建。
本例涉及的数据库表country,比官网实例中多了一个字段:continent,手动加上亦可:

CREATE TABLE `country` (
  `code` CHAR(2) NOT NULL PRIMARY KEY,
  `name` CHAR(52) NOT NULL,
  `continent` CHAR(52) NOT NULL,
  `population` INT(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `country` VALUES ('AU','Australia',24016400,'Oceania');
INSERT INTO `country` VALUES ('BR','Brazil',205722000,'South America');
INSERT INTO `country` VALUES ('CA','Canada',35985751,'North America');
INSERT INTO `country` VALUES ('CN','China',1375210000,'Asia');
INSERT INTO `country` VALUES ('DE','Germany',81459000,'Europe');
INSERT INTO `country` VALUES ('FR','France',64513242,'Europe');
INSERT INTO `country` VALUES ('GB','United Kingdom',65097000,'Europe');
INSERT INTO `country` VALUES ('IN','India',1285400000,'Asia');
INSERT INTO `country` VALUES ('RU','Russia',146519759,'Europe');
INSERT INTO `country` VALUES ('US','United States',322976000,'North America');

欢迎深入阅读:
一处编写,三处运行的Yii2表单验证

(全文完)

相关文章

  • Yii2的表单验证之三:Ajax验证

    Yii2具有强大的表单验证功能,能用好表单验证,用户输入就基本掌握了,在这里我和各位聊聊Yii2的Ajax验证器。...

  • Yii2的表单验证之一:客户端验证.

    Yii2具有强大的表单验证功能,能用好表单验证,用户输入就基本掌握了,在这里我和各位聊聊Yii2的客户端验证器。所...

  • Yii2的表单验证之二:服务器端验证

    Yii2具有强大的表单验证功能,能用好表单验证,用户输入就基本掌握了,在这里我和各位聊聊Yii2的服务器端验证器。...

  • 2018-08-11

    登录 ----- *双向验证 *ajax提交表单

  • Laravel 之 验证 validate 验证问题

    1. 表单提交验证 2. 使用ajax发送请求验证

  • 项目简介

    登录 --- * 双向验证 * ajax提交表单(CSRF攻击) 注册 --- * 手机号和邮箱的验证 * 发送短...

  • php yii2 表单提交CSRF验证

    Yii2表单提交默认需要验证CSRF,如果CSRF验证不通过,则表单提交失败,解决方法如下: 第一种解决办法是关闭...

  • 项目简介

    登陆 --- *双向验证数据 *ajax 提交表单(CSRF攻击) 注册 --- *手机号和邮箱的验证 *发送短信...

  • HTTP --- 验证

    在控制器中 验证 请求数据 表单请求验证 其他(Ajax请求验证) 手动验证器(就是在控制器中使用Validaor...

  • Yii2 笔记

    1、提交表单开启ajax异步验证唯一性

网友评论

      本文标题:Yii2的表单验证之三:Ajax验证

      本文链接:https://www.haomeiwen.com/subject/rziqfxtx.html