BootstrapValidator实现注册校验和登录错误提示效果


Posted in Javascript onMarch 10, 2017

使用BootstrapValidator进行注册校验和登录错误提示,具体内容如下

1、介绍

在AdminEAP框架中,使用了BootstrapValidator校验框架,本文以注册校验的用户名、登录名、密码、确认密码的校验(后面还有时间区间、服务器校验)为例,讲述BootstrapValidator的使用。同时以登录错误提示为例,说明如何在动态改变组件的错误提示信息。

先看下面的注册与登录的校验效果图:

注册校验:

BootstrapValidator实现注册校验和登录错误提示效果

登录错误提示:根据不同的错误类型,动态改变组件的样式和错误提示内容

BootstrapValidator实现注册校验和登录错误提示效果

BootstrapValidator实现注册校验和登录错误提示效果

2、注册校验

1、头部引入bootstrap-validator.css

<link rel="stylesheet"  href="${basePath}/resources/adminlte/plugins/bootstrap-validator/dist/css/bootstrap-validator.css" rel="external nofollow" />

${basePath}为系统的路径变量

2、form组件

 

<form action="${basePath}/oauth/register" method="post" id="register-form">
      <input type="hidden" name="oAuthId" value="${oAuthInfo.oAuthId?default('-1')}">
      <input type="hidden" name="oAuthType" value="${oAuthInfo.oAuthType?default('-1')}">
      <div class="form-group has-feedback">
        <input type="text" class="form-control" name="userName" id="userName" placeholder="请输入用户名" required>
        <span class="glyphicon glyphicon-user form-control-feedback"></span>
      </div>
      <div class="form-group has-feedback">
        <input type="text" class="form-control" name="loginName" id="loginName" placeholder="请输入登录邮箱/登录名">
        <span class="glyphicon glyphicon-envelope form-control-feedback"></span>
      </div>
      <div class="form-group has-feedback">
        <input type="password" class="form-control" name="password" id="password" placeholder="请输入密码">
        <span class="glyphicon glyphicon-lock form-control-feedback"></span>
      </div>
      <div class="form-group has-feedback">
        <input type="password" class="form-control" name="repassword" id="repassword" placeholder="再次确认密码">
        <span class="glyphicon glyphicon-log-in form-control-feedback"></span>
      </div>
      <div class="row">
        <div class="col-xs-12">
          <div class="checkbox icheck">
            <label>
              <input type="checkbox" name="rememberMe" required> 同意遵循<a href="#" rel="external nofollow" >AdminEAP协议</a>
            </label>
          </div>
        </div>
        <!-- /.col -->
      </div>
      <div class="row">
        <div class="col-xs-12">
          <button type="submit" class="btn btn-danger btn-block btn-flat">注 册</button>
        </div>
      </div>
    </form>

3、引入bootstrap-validator.js

<script src="${basePath}/resources/adminlte/bootstrap/js/bootstrap.min.js"></script>

4、校验的核心js代码

<script>
  $(function () {
    //将checkbox渲染为icheck样式
    $('input').iCheck({
      checkboxClass: 'icheckbox_square-red',
      radioClass: 'iradio_square-red',
      increaseArea: '20%' // optional
    });

    //此处为校验的核心代码
    $("#register-form").bootstrapValidator({
      submitHandler: function (valiadtor, loginForm, submitButton) {

        valiadtor.defaultSubmit();
      },
      fields: {
        userName: {
          validators: {
            notEmpty: {
              message: '用户名不能为空'
            },
            stringLength: {
              /*长度提示*/
              min: 4,
              max: 30,
              message: '用户名长度必须在4到30之间'
            }
          }
        },
        loginName: {
          validators: {
            notEmpty: {
              message: '登录邮箱名或用户名不能为空'
            },
            stringLength: {
              /*长度提示*/
              min: 4,
              max: 30,
              message: '用户名长度必须在4到30之间'
            },
            threshold: 4,//只有4个字符以上才发送ajax请求
            remote: {
              url: "${basePath}/oauth/checkUnique",
              data: function (validator) {
                return {
                  loginName: $("#loginName").val(),
                  userId: null
                };
              },
              message: '该登录名已被使用,请使用其他登录名',
              delay:2000
            }
          }
        },
        password: {
          validators: {
            notEmpty: {
              message: '密码不能为空'
            },
            stringLength: {
              /*长度提示*/
              min: 6,
              max: 30,
              message: '密码长度必须在6到30之间'
            },
            different: {//不能和用户名相同
              field: 'loginName',//需要进行比较的input name值
              message: '不能和用户名相同'
            },
            regexp: {
              regexp: /^[a-zA-Z0-9_\.]+$/,
              message: '密码由数字字母下划线和.组成'
            }
          }
        },
        repassword: {
          message: '密码无效',
          validators: {
            notEmpty: {
              message: '密码不能为空'
            },
            stringLength: {
              min: 6,
              max: 30,
              message: '用户名长度必须在6到30之间'
            },
            identical: {//相同
              field: 'password',
              message: '两次密码不一致'
            },
            different: {//不能和用户名相同
              field: 'loginName',
              message: '不能和用户名相同'
            },
            regexp: {//匹配规则
              regexp: /^[a-zA-Z0-9_\.]+$/,
              message: '密码由数字字母下划线和.组成'
            }
          }
        }

      }
    });

  });

5、登录名唯一性校验的后台代码

/**
   * 校验当前登录名/邮箱的唯一性
   * @param loginName 登录名
   * @param userId 用户ID(用户已经存在,即又改回原来的名字还是唯一的)
   * @return
   */
  @RequestMapping(value = "/oauth/checkUnique", method = RequestMethod.POST)
  @ResponseBody
  public Map checkExist(String loginName, String userId) {
    Map<String, Boolean> map = new HashMap<String, Boolean>();
    User user = userService.getUserByLoginName(loginName);
    //用户不存在,校验有效
    if (user == null) {
      map.put("valid", true);
    } else {
      //用户存在(存在的用户是当前用户,登录名一致,校验通过,否则校验不通过)
      if(!StrUtil.isEmpty(userId)&&userId.equals(user.getLoginName())){
        map.put("valid",true);
      }else {
        map.put("valid", false);
      }
    }
    return map;
  }

以上的配置完成了注册文本框的各种校验,更多的校验内容,可以查看相关的bootstrap-validator的API文档。

3、登录错误动态提示

1、在后台登录时,会抛出各种登录不成功的提示,需要动态改变前端组件的错误提示信息。不同类型的错误信息编码,要控制不同的组件样式和提示内容。以下是后台抛出的错误类型和错误信息(使用shiro认证)。

try {
      subject.login(token);
      //通过认证
      if (subject.isAuthenticated()) {
        Set<String> roles = roleService.getRoleCodeSet(userName);
        if (!roles.isEmpty()) {
          subject.getSession().setAttribute("isAuthorized", true);
          return MAIN_PAGE;
        } else {//没有授权
          msg = "您没有得到相应的授权!";
          model.addAttribute("message", new ResultCode("1", msg));
          subject.getSession().setAttribute("isAuthorized", false);
          LOGGER.error(msg);
          return LOGIN_PAGE;
        }

      } else {
        return LOGIN_PAGE;
      }
      //0 未授权 1 账号问题 2 密码错误 3 账号密码错误
    } catch (IncorrectCredentialsException e) {
      msg = "登录密码错误. Password for account " + token.getPrincipal() + " was incorrect";
      model.addAttribute("message", new ResultCode("2", msg));
      LOGGER.error(msg);
    } catch (ExcessiveAttemptsException e) {
      msg = "登录失败次数过多";
      model.addAttribute("message", new ResultCode("3", msg));
      LOGGER.error(msg);
    } catch (LockedAccountException e) {
      msg = "帐号已被锁定. The account for username " + token.getPrincipal() + " was locked.";
      model.addAttribute("message", new ResultCode("1", msg));
      LOGGER.error(msg);
    } catch (DisabledAccountException e) {
      msg = "帐号已被禁用. The account for username " + token.getPrincipal() + " was disabled.";
      model.addAttribute("message", new ResultCode("1", msg));
      LOGGER.error(msg);
    } catch (ExpiredCredentialsException e) {
      msg = "帐号已过期. the account for username " + token.getPrincipal() + " was expired.";
      model.addAttribute("message", new ResultCode("1", msg));
      LOGGER.error(msg);
    } catch (UnknownAccountException e) {
      msg = "帐号不存在. There is no user with username of " + token.getPrincipal();
      model.addAttribute("message", new ResultCode("1", msg));
      LOGGER.error(msg);
    } catch (UnauthorizedException e) {
      msg = "您没有得到相应的授权!" + e.getMessage();
      model.addAttribute("message", new ResultCode("1", msg));
      LOGGER.error(msg);
    }

2、前端核心JS代码

<script>
    $(function () {
      $('input').iCheck({
        checkboxClass: 'icheckbox_square-red',
        radioClass: 'iradio_square-red',
        increaseArea: '20%' // optional
      });

      fillbackLoginForm();
      $("#login-form").bootstrapValidator({
        message:'请输入用户名/密码',
        submitHandler:function (valiadtor,loginForm,submitButton) {
          rememberMe($("input[name='rememberMe']").is(":checked"));
          valiadtor.defaultSubmit();
        },
        fields:{
          userName:{
            validators:{
              notEmpty:{
                message:'登录邮箱名或用户名不能为空'
              }
            }
          },
          password:{
            validators:{
              notEmpty:{
                message:'密码不能为空'
              }
            }
          }
        }
      });
      <!--freemark语法,查看是否从后台传送过来错误信息,并初始化错误提示组件LoginValidator-->
      <#if message??>
        new LoginValidator({
          code:"${message.code?default('-1')}",
          message:"${message.message?default('')}",
          userName:'userName',
          password:'password'
        });
      </#if>
    });

    //使用本地缓存记住用户名密码
    function rememberMe(rm_flag){
      //remember me
      if(rm_flag){
         localStorage.userName=$("input[name='userName']").val();
         localStorage.password=$("input[name='password']").val();
        localStorage.rememberMe=1;
      }
      //delete remember msg
      else{
        localStorage.userName=null;
        localStorage.password=null;
        localStorage.rememberMe=0;
      }
    }

    //记住回填
    function fillbackLoginForm(){
      if(localStorage.rememberMe&&localStorage.rememberMe=="1"){
        $("input[name='userName']").val(localStorage.userName);
        $("input[name='password']").val(localStorage.password);
        $("input[name='rememberMe']").iCheck('check');
        $("input[name='rememberMe']").iCheck('update');
      }
    }
  </script>

3、LoginValidator组件的代码 login.js

/**
 * Created by billJiang on 2017/1/12.
 * 登录异常信息显示
 */

function LoginValidator(config) {
  this.code = config.code;
  this.message = config.message;
  this.userName = config.userName;
  this.password = config.password;
  this.initValidator();
}

//0 未授权 1 账号问题 2 密码错误 3 账号密码错误
LoginValidator.prototype.initValidator = function () {
  if (!this.code)
    return;
  if(this.code==0){
    this.addPasswordErrorMsg();
  }else if(this.code==1){
    this.addUserNameErrorStyle();
    this.addUserNameErrorMsg();
  }else if(this.code==2){
    this.addPasswordErrorStyle();
    this.addPasswordErrorMsg();
  }else if(this.code==3){
    this.addUserNameErrorStyle();
    this.addPasswordErrorStyle();
    this.addPasswordErrorMsg();
  }
  return;
}

LoginValidator.prototype.addUserNameErrorStyle = function () {
  this.addErrorStyle(this.userName);
}

LoginValidator.prototype.addPasswordErrorStyle = function () {
  this.addErrorStyle(this.password);
}

LoginValidator.prototype.addUserNameErrorMsg = function () {
  this.addErrorMsg(this.userName);
}

LoginValidator.prototype.addPasswordErrorMsg = function () {
  this.addErrorMsg(this.password);
}


LoginValidator.prototype.addErrorMsg=function(field){
  $("input[name='"+field+"']").parent().append('<small data-bv-validator="notEmpty" data-bv-validator-for="'+field+'" class="help-block">' + this.message + '</small>');
}

LoginValidator.prototype.addErrorStyle=function(field){
  $("input[name='" + field + "']").parent().addClass("has-error");
}

以上把错误提示封装成了一个LoginValidator组件,方便前端调用,增强代码的可维护性,因为没有找到Bootstrap-validator改变错误提示的接口,所以查看了源码之后做了封装。

4、补充

1、时间区间校验

"startTime":{
          validators:{
            date:{
              format:'YYYY-MM-DD HH:mm',
              message:'日期格式不正确'
            },
            callback:{
              callback:function(value,validator){
                var startTime=value;
                var endTime=$("#endTime").val();
                if(startTime&&endTime){
                  return DateDiff(endTime,startTime)>0;
                }else{
                  return true;
                }

              },
              message:'结束时间不能小于开始时间'
            }
          }
        },
        "endTime":{
          validators:{
            date:{
              format:'YYYY-MM-DD HH:mm',
              message:'日期格式不正确'
            },
            callback:{
              callback:function(value,validator){
                var startTime=$("#startTime").val();
                var endTime=value;
                if(startTime&&endTime){
                  return DateDiff(endTime,startTime)>0;
                }else{
                  return true;
                }

              },
              message:'结束时间不能小于开始时间'
            }

          }
        },

2、服务器校验

"jobClass": {
    validators: {
        notEmpty: {message: '执行类名不能为空'},
        remote:{
          url:basePath+"/job/checkJobClass",
          data: function(validator) {
            return {
              jobClass:$('#jobClass').val(),
            };
          },
          message:'该执行类不存在'
        }
      }
    }

后台代码

@RequestMapping(value="/checkJobClass",method = RequestMethod.POST)
  @ResponseBody
  public Map checkJobClass(String jobClass){
    Map map=new HashMap<>();
    try {
      Class<?> objClass = Class.forName(jobClass);
      if(objClass!=null)
      map.put("valid", true);
      return map;
    } catch (Exception ex) {
      logger.error(ex.getMessage().toString());
      map.put("valid", false);
      return map;
    }
  }

Github: https://github.com/bill1012
AdminEAP:http://www.admineap.com

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
去除链接虚线全面分析总结
Aug 15 Javascript
Prototype1.5 rc2版指南最后一篇之Position
Jan 10 Javascript
javascript 全等号运算符使用说明
May 31 Javascript
jQuery操作元素css样式的三种方法
Jun 04 Javascript
js控制页面的全屏展示和退出全屏显示的方法
Mar 10 Javascript
javascript实现PC网页里的拖拽效果
Mar 14 Javascript
jquery Deferred 快速解决异步回调的问题
Apr 05 Javascript
利用Angularjs中模块ui-route管理状态的方法
Dec 27 Javascript
jQuery html表格排序插件tablesorter使用方法详解
Feb 10 Javascript
基于Vue2实现的仿手机QQ单页面应用功能(接入聊天机器人 )
Mar 30 Javascript
Vue.js 实现数据展示全部和收起功能
Sep 05 Javascript
实例详解带参数的 npm script
May 28 Javascript
Bootstrap fileinput组件封装及使用详解
Mar 10 #Javascript
Bootstrap栅格系统使用方法及页面调整变形的解决方法
Mar 10 #Javascript
Node.js中.pfx后缀文件的处理方法
Mar 10 #Javascript
Vue.js结合bootstrap实现分页控件
Mar 10 #Javascript
js获取ip和地区
Mar 10 #Javascript
Vue.js bootstrap前端实现分页和排序
Mar 10 #Javascript
JavaScript组件开发之输入框加候选框
Mar 10 #Javascript
You might like
php数字转汉字代码(算法)
2011/10/08 PHP
PHP通过内置函数memory_get_usage()获取内存使用情况
2014/11/20 PHP
php版银联支付接口开发简明教程
2016/10/14 PHP
PHP使用GD库制作验证码的方法(点击验证码或看不清会刷新验证码)
2017/08/15 PHP
PHPMailer ThinkPHP实现自动发送邮件功能
2018/06/10 PHP
php实现在线考试系统【附源码】
2018/09/18 PHP
javascript 哈希表(hashtable)的简单实现
2010/01/20 Javascript
Javascript中valueOf与toString区别浅析
2013/03/19 Javascript
一个奇葩的最短的 IE 版本判断JS脚本
2014/05/28 Javascript
微信JSSDK上传图片
2015/08/23 Javascript
基于jquery实现弹幕效果
2016/09/29 Javascript
如何使用headjs来管理和异步加载js
2016/11/29 Javascript
vue 表单输入格式化中文输入法异常问题
2018/05/30 Javascript
傻瓜式解读koa中间件处理模块koa-compose的使用
2018/10/30 Javascript
jQuery中DOM常见操作实例小结
2019/08/01 jQuery
基于layui轮播图满屏是高度自适应的解决方法
2019/09/16 Javascript
解决layui批量传值到后台操作时出现传值为空的问题
2019/09/28 Javascript
一起写一个即插即用的Vue Loading插件实现
2019/10/31 Javascript
vue实现匀速轮播效果
2020/06/29 Javascript
JavaScript DOM常用操作代码汇总
2020/07/03 Javascript
基于Python实现的扫雷游戏实例代码
2014/08/01 Python
pandas dataframe添加表格框线输出的方法
2019/02/08 Python
浅谈PyQt5中异步刷新UI和Python多线程总结
2019/12/13 Python
Python3 Tensorlfow:增加或者减小矩阵维度的实现
2020/05/22 Python
基于python爬取梨视频实现过程解析
2020/11/09 Python
CSS3 实现发光边框特效
2020/11/11 HTML / CSS
美国复古街头服饰精品店:Need Supply Co.
2017/02/22 全球购物
美国休闲服装品牌:J.Crew Factory
2017/03/04 全球购物
求高于平均分的学生学号及成绩
2016/09/01 面试题
学生个人求职自荐信格式
2013/09/23 职场文书
大专毕业自我鉴定
2014/02/04 职场文书
观看《永远的雷锋》心得体会
2014/03/12 职场文书
刑事辩护词范文
2015/05/21 职场文书
宪法宣传标语100条
2019/10/15 职场文书
Python基本的内置数据类型及使用方法
2022/04/13 Python
SQLServer常见数学函数梳理总结
2022/08/05 MySQL