在传统的前后一体项目开发中,大部分人会使用到BootStrap加其它JS组件的配合方式来完成页面UI功能的实现。下面介绍几种常用的JS库的使用方法。代码例子下载
目录
1 树形组件
树组件是管理系统开发中最常使用到的组件之一,这样引用的js组件库是jqtree。 jqtree使用的API参考http://mbraak.github.io/jqTree/ 官方文档。
- jqtree - 组件的简单效果。
Maven项目导入pom.xml依赖
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>jqtree</artifactId>
<version>1.1.0</version>
</dependency>
1.1 TreeJS静态例子
//树形结构的json
var data = [
{
name: '机关',
id:'1',
children: [
{ name: '人事部门', id:'11' },
{ name: '综合' , id:'12' },
{ name: '财务' , id:'13' }
]
},
{
name: '生产事业部',
children: [
{ name: '一工区' },
{ name: '二工区' }
]
},
{
name: '汽运输部',
children: [
{ name: '一队' },
{ name: '二队' }
]
}
];
//创建树组件
$('#tree1').tree({data: data });
完整的静态例子
<html>
<head>
<meta charset="UTF-8">
<title>SpringBoot + webjars</title>
<!-- Bootstrap CSS CDN -->
<link rel="stylesheet" href="webjars/bootstrap/5.1.3/css/bootstrap.min.css"/>
<link rel="stylesheet" href="webjars/bootstrap-icons/1.8.3/font/bootstrap-icons.css"/>
<!-- Our Custom CSS -->
<link rel="stylesheet" href="css/style.css?v=1">
<script src="webjars/jquery/3.6.0/jquery.min.js"></script>
<!-- Bootstrap JS -->
<script src="webjars/bootstrap/5.1.3/js/bootstrap.min.js"></script>
<!-- 树形组件 JS -->
<script src="webjars/jqtree/1.1.0/tree.jquery.js"></script>
<link rel="stylesheet" href="webjars/jqtree/1.1.0/jqtree.css"/>
</head>
<body>
<div class="container">
<div class="row">
<div class="col" id="tree1">
</div>
<div class="col-8">
内容
</div>
</div>
</div>
<script>
var data = [
{
name: '机关',
id:'1',
children: [
{ name: '人事部门', id:'11' },
{ name: '综合' , id:'12' },
{ name: '财务' , id:'13' }
]
},
{
name: '生产事业部',
children: [
{ name: '一工区' },
{ name: '二工区' }
]
},
{
name: '汽运输部',
children: [
{ name: '一队' },
{ name: '二队' }
]
}
];
$('#tree1').tree({data: data });
/********** 点击事件 ***********/
$('#tree1').on(
'tree.click',
function(event) {
// 'event.node' 获得数据元素
var node = event.node;
alert(node.id+" "+node.name);
}
);
</script>
</body>
</html>
1.2 动态生产组件
1 创建Controller
在Spring boot项目中创建一个Controller容器DeptController ,DeptController中增加树结构的查询方法deptTree,deptTree方法中创建树节点Node
对象层次结构。为了操作简单,我们使用List和Map来描述树形数据。
@RestController()
@RequestMapping( "/dept")
public class DeptController {
//部门数结构
@GetMapping(path = "/deptTree")
public List deptTree(Model model) {
return deptTreeList();
}
public List deptTreeList() {
List<Map> nodes = new ArrayList<>();
nodes.add(getNodesList(
getNodes("1","机关"),
getNodes("11","人事部门"),
getNodes("12","综合")));
nodes.add(getNodesList(
getNodes("2","生产部"),
getNodes("11","一工区"),
getNodes("12","二工区")));
nodes.add(getNodesList(
getNodes("3","汽运部"),
getNodes("11","一队"),
getNodes("12","二队")));
return nodes;
}
public Map getNodes(String id,String name){
Map map=new HashMap();
map.put("id",id);
map.put("name",name);
map.put("children",new ArrayList());
return map;
}
public Map getNodesList(Map map,Map... child){
List childlist=(List)map.get("children");
Arrays.stream(child).forEach(x->{
childlist.add(x);
});
return map;
}
}
2 html页面中访问url
通过组件中的dataUrl方法来访问Spring boot 容器中的url路径。
$(‘#tree1’).tree({dataUrl:‘/dept/deptTree’,autoOpen: true});
<div class="container">
<div class="row">
<div class="col" id="tree1">
</div>
<div class="col-8">
</div>
</div>
</div>
<script>
/********* url访问 /dept/deptTree **********/
$('#tree1').tree({dataUrl:'/dept/deptTree',autoOpen: true});
/********** 点击事件 ***********/
$('#tree1').on(
'tree.click',
function(event) {
// 'event.node' 获得数据元素
var node = event.node;
alert(node.id+" "+node.name);
}
);
</script>
jqtree组件中的dataUrl json参数与Jquery.ajax相同,可以参照Jquery.ajax参数来设置。
$('#tree1').tree({
dataUrl: {
url: '/example_data.json',
headers: {'abc': 'def'}
}
});
2 简单 TABEL 生成
Tabel生成使用Jquery+Template 模板解析加Bootstrap5 UI,来生成页面中Tabel 列表内容。在js函数中拼接 Template
模板字符串,生产table组件中的 tr元素内容。
模板
js自带的Template语法。
`<tr><th>${user.dept}</th><th>${user.name}</th><th>${user.nub}</th><th>${user.sex}</th></tr>`;
html页面例子
Jquery.ajax方法$.get()获得到 JSON字符串, $.each()循环拼接出列表内容。
<div class="container">
<div class="row">
<div class="col" id="tree1">
</div>
<div class="col-9">
<table id="example"
class="table table-bordered"
style="width: 100%">
<thead>
<tr>
<th>部门</th>
<th>名称</th>
<th>工号</th>
<th>性别</th>
</tr>
</thead>
<tbody id="tab">
</tbody>
</table>
</div>
</div>
</div>
<script>
$.get('/dept/userTabel',function(data,status){
$('#tab').html('');
$.each(data,function(index,value){
//字符串模板
$('#tab').append(zht(value));
});
});
function zht(user){
return `<tr><td>${user.dept}</td><td>${user.name}</td><td>${user.nub}</td><th>${user.sex}</th></tr>`;
}
</script>
Controller代码
在Spring boot项目中创建业务处理Controller容器 ,在容器中创建一个查询方法userTabel。在查询方法中生产页面table组件所需要的json数据结构。
@RestController()
@RequestMapping( "/dept")
public class DeptController {
//人员信息内容
@GetMapping(path = "/userTabel")
public List userTabel(Model model) {
Map p1=new HashMap();
p1.put("dept","部门一");
p1.put("name","张**");
p1.put("sex","男");
p1.put("nub","11");
p1.put("id","1");
Map p2=new HashMap();
p2.put("dept","部门一");
p2.put("name","王**");
p2.put("sex","女");
p2.put("nub","55");
p2.put("id","2");
List list=new ArrayList();
list.add(p1);
list.add(p2);
return list;
}
}
3 分页功能
在做分页功能的时候,找的很多分页js库,在使用的时候都不满意,不是封装的太重了,就是使用起来太繁琐,操作性差扩展性更差。于是自己写了一个分页js组件,在调用和扩展的时候能简单点。在通过jquery ajax与后端通信产生的json来生成Bootstrap TABEL列表的分页功能。
分页脚本
function ZhtPegeHmltx(id){
var that = this;
this.objid=id;
//清理浏览器
document.execCommand("BackgroundImageCache", false, true);
//分页数
this.pagesize=5;
//当前页数位置
this.justpage=2;
//总页数
this.sumpage=10;
//总条数
this.sumnumber=120;
this.objpage=null;
this.objmain=null;
//初始化
this.firdiv=null;//首元素
this.obj=null;//页面元素
this.arry = new Array();
this.pageconf={};//分页数据算法
this.init=function(){
if(this.objid==null){
alert('查不到引入元素');
return;
}
if(this.pageconf==null){
alert('没有导入分页配置信息');
return;
}
this.divpage();
}
this.divpage=function(){
this.JsonFor();
this.objmain=document.getElementById(this.objid);
if(this.objpage!=null){
$(this.objpage).remove();
}
this.objpage=document.createElement("DIV");
this.Onfirdiv();
this.OnPage();
//this.OnLast();
this.OnFindPageUrl();
this.objmain.appendChild(this.objpage);
}
this.Onfirdiv=function(){
var str='总共'+this.pageconf.sumcount+'条';
this.firdiv=document.createElement("DIV");
this.firdiv.innerHTML=str;
this.firdiv.className="pagetile";
this.objpage.appendChild(this.firdiv);
}
this.OnLast=function(){
var str=this.pageconf.page+'/'+this.pageconf.sumpage+'页';
this.firdiv=document.createElement("DIV");
this.firdiv.innerHTML=str;
this.firdiv.className="pagetile";
this.objpage.appendChild(this.firdiv);
}
this.OnPage=function(){
this.obj=this.t_creator("pagination");
this.obj.appendChild(this.t_creaeDefLi('首页',1));
this.obj.appendChild(this.t_creaeDefLi('上一页',this.pagefr));
for(var i=this.st+1;i<=this.send;i++){
if(i<=this.pageconf.sumpage){
this.arry[i]=this.t_creaLi(i);
this.obj.appendChild(this.arry[i]);
}
}
this.obj.appendChild(this.t_creaeDefLi(this.pagelast+' 下一页',this.pagelast));
this.obj.appendChild(this.t_creaeDefLi('最后一页',this.pageconf.sumpage));
this.objpage.appendChild(this.obj);
}
this.t_creator=function(name){
var t=document.createElement("ul");
t.className=name;
return t;
}
this.t_creaLi=function(name){//分页内容
var l=document.createElement("Li");
l.innerHTML='<a class="page-link">'+name+'</a>';
l.className="page-item";
l.setAttribute("page",name);
if(name==this.pageconf.page){
l.className="page-item active";
}
return l;
}
this.t_creaeDefLi=function(name,nub){
var l=document.createElement("Li");
l.setAttribute("page",nub);
l.className="page-item";
l.innerHTML='<a class="page-link">'+name+'</a>';
return l;
}
ZhtPegeHmltx.prototype.setPageconf = function(pageconf){
if(pageconf!=null){
this.pageconf=pageconf;
this.init();
}
}
this.st=0;
this.send=0;
this.pagecoutn=5;
this.pagelast=6;
this.pagefr=1;
this.JsonFor=function(){
if(this.pageconf.page==null){
return;
}
if(this.pageconf.page==null){
return;
}
this.st=parseInt(this.pageconf.page/this.pagecoutn)*this.pagecoutn;
if(this.st==this.pageconf.page){
this.st=this.st-this.pagecoutn;
}
this.send=this.st+this.pagecoutn;
this.pagelast= this.send+1;//下一页 5+1
if( this.pagelast>=this.pageconf.sumpage){
this.pagelast=this.pageconf.sumpage;
}
this.pagefr=this.st;
if(this.pagefr<1){
this.pagefr=1;
}
}
//方法监听 onCreateTempleDiv 接口为被监听方法
this.OnFindPageUrl=function(){
$(this.objpage).on("click","li",function(){
var id=this.getAttribute('page');
if(id!=null){
return onCreateTempleDiv(id);
}
if(this.innerHTML==''){
return;
}
return onCreateTempleDiv(this.innerHTML);
});
}
}
HTML页面中调用方法
<style>
.pagetile {
color: black;
float: left;
padding: 8px 16px;
text-decoration: none;
transition: background-color .3s;
margin: 0 4px;
}
</style>
<div style="padding:10px;width:90%" id="tz1"></div>
<script>
var z=new ZhtPegeHmltx('tz1');
z.setPageconf({count:10,page:6,sumcount:150,sumpage:14});
//分页点击事件
function onCreateTempleDiv(id){
var obj={count:10,page:id,sumcount:150,sumpage:14};
z.setPageconf(obj);
}
</script>
Spring boot 项目中分页使用
创建分页pojo
public class PagePojo {
public List list=new ArrayList();
public int count=10;//每页数量
public int page=1;//当前页
public int sumcount;//总数量
public int sumpage;//总页数
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getPage() {
return page;
}
public void setPage(int page) {
if(page<=0){
page=1;
}
this.page = page;
}
public int getSumcount() {
return sumcount;
}
public void setSumcount(int sumcount) {
this.sumcount = sumcount;
}
public int getSumpage() {
return sumcount/count;
}
public void setSumpage(int sumpage) {
this.sumpage = sumpage;
}
}
Controller分页设置
@RestController()
@RequestMapping( "/dept")
public class DeptController {
@GetMapping(path = "/userTabel")
public PagePojo userTabel(int page) {
List list=new ArrayList();
for(int i=1;i<10;i++){
Map p1=new HashMap();
p1.put("dept","部门"+page);
p1.put("name","张*"+page);
p1.put("sex","男");
p1.put("nub","11");
p1.put("id",i);
list.add(p1);
}
PagePojo p=new PagePojo();
p.setList(list);
p.setPage(page);
p.setSumcount(132);
return p;
}
}
html页面
<table id="example"
class="table table-bordered"
style="width: 100%">
<thead>
<tr>
<th>部门</th>
<th>名称</th>
<th>工号</th>
<th>性别</th>
<th>修改</th>
</tr>
</thead>
<tbody id="tab">
</tbody>
</table>
<------------ 分页组件 --------------->
<div style="padding:10px;width:90%" id="tz1"></div>
<script>
var zht=new ZhtPegeHmltx('tz1');
//查询列表内容与分页显示
function findtable(id){
$.get('/dept/userTabel?page='+id,function(data,status){
$('#tab').html('');
zht.setPageconf(data);
$.each(data.list,function(index,value){
$('#tab').append(createTd(value));
});
});
}
//列表 tr td内容
function createTd(user){
return `<tr><td>${user.dept}</td><td>${user.name}</td><td>${user.nub}</td><td>${user.sex}</td><td><button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-id="${user.id}">修改</button></td></tr>`;
}
//分页事件监听方法
function onCreateTempleDiv(id){
findtable(id);
}
//初始化列表
findtable(1);
</script>
效果图
4 日期范围控件
Spring boot +Thymeleaf 使用日期选择器组件daterangepicker 。
- daterangepicker - 日期范围选择器组件库。官网地址https://www.daterangepicker.cn/
Maven项目导入pom.xml依赖
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap-daterangepicker</artifactId>
<version>3.1</version>
</dependency>
daterangepicker组件库使用必须同时和momentjs组件一起使用,在导入bootstrap-daterangepicker 组件pom的时候momentjs的pom也一同导入了,不需要单独导入。
<html>
<head>
<meta charset="UTF-8">
<title>SpringBoot + webjars</title>
<script src="webjars/momentjs/2.29.4/moment.js"></script>
<script src="webjars/bootstrap-daterangepicker/3.1/js/bootstrap-daterangepicker.js"></script>
<link rel="stylesheet" href="webjars/bootstrap-daterangepicker/3.1/css/bootstrap-daterangepicker.css"/>
</head>
html页面元素与js脚本使用
<div class="container">
<form method="post" >
<div class="row">
<div class="col ">
<label for="dateRange">时间选择</label>
<div class="input-group">
<input type="text" class="form-control" id="dateRange" autocomplete="off"/>
<input type="hidden" name="datestar" />
<input type="hidden" name="dateend" />
</div>
</div>
<div class="col ">
<button class="btn btn-primary" type="submit">查询</button>
</div>
</div>
</form>
</div>
</div>
<script>
var locale = {
"format": 'YYYY-MM-DD',
"separator": " / ",
"applyLabel": "确定",
"cancelLabel": "取消",
"fromLabel": "起始时间",
"toLabel": "结束时间",
"customRangeLabel": "自定义",
"weekLabel": "W",
"daysOfWeek": ["日", "一", "二", "三", "四", "五", "六"],
"monthNames": ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
"firstDay": 1
};
var $dateRange = $('#dateRange');
$dateRange.daterangepicker({
format: "YYYY-MM-DD",
startDate: new Date(),
autoclose: true,
todayBtn: true,
locale:locale
});
$dateRange.on('apply.daterangepicker', function (ev, picker) {
$('input[name="datestar"]').val(picker.startDate.format('YYYY-MM-DD'));
$('input[name="dateend"]').val(picker.endDate.format('YYYY-MM-DD'));
});
</script>
需要自己定义汉化内容
var locale = {
“format”: ‘YYYY-MM-DD’,
“separator”: " / ",
“applyLabel”: “确定”,
“cancelLabel”: “取消”,
“fromLabel”: “起始时间”,
“toLabel”: “结束时间”,
“customRangeLabel”: “自定义”,
“weekLabel”: “W”,
“daysOfWeek”: [“日”, “一”, “二”, “三”, “四”, “五”, “六”],
“monthNames”: [“一月”, “二月”, “三月”, “四月”, “五月”, “六月”, “七月”, “八月”, “九月”, “十月”, “十一月”, “十二月”],
“firstDay”: 1
};
单选日期
<label for="message-text"
class="col-form-label">日期:</label>
<input type="text" class="form-control"
id="dateRange" autocomplete="off"/>
<script>
var $dateRange = $('#dateRange');
$dateRange.daterangepicker({
singleDatePicker:true,
showDropdowns:true,
format: "YYYY-MM-DD",
startDate: new Date()
});
</script>
5 FROM 属性内容
简单的介绍bootstrap5中自带的FROM元素使用与验证功能,为了实现更多的表单验证功能的需要引入第三方验证js组件。
5.1 bootstrap5中FROM使用
from表单使用Bootstrap 5 自带的基础UI元素来完成
- form-label label标签元素添加这个类,保持标签元素填充状态
- form-select 类添加到 中为下拉列表状态
- was-validated 添加到form 中为验证状态,对应其他元素中的required
user.html代码
<form class="was-validated" id="userfrom">
<div class="mb-3">
<label for="message-text"
class="form-label">名称:</label>
<input type="text"
class="form-control" id="name" required></input>
</div>
<div class="mb-3">
<label for="message-text"
class="form-label">部门:</label>
<select class="form-select" required>
<option th:each="d:${dept}"
th:value="${d.value}"
th:text="${d.name}"></option>
</select>
</div>
<div class="mb-3">
<label for="message-text"
class="form-label">mail:</label>
<input type="email"
class="form-control"
autocomplete="off" required/>
</div>
<div class="mb-3">
<label for="message-text"
class="form-label">年龄(20-100):</label>
<input type="number"
class="form-control"
id="age" autocomplete="off"
min="20" max="100" required/>
</div>
<div class="mb-3">
<label for="message-text"
class="form-label">日期:</label>
<input type="text" class="form-control"
id="dateRange" autocomplete="off"/>
</div>
<div class="mb-3">
<label for="message-text" class="col-form-label">备注:</label>
<textarea class="form-control" id="message-text"></textarea>
</div>
<div class="mb-3">
<label for="message-text" class="col-form-label">性别:</label>
<div class="row">
<div class="col-sm-1 form-check">
<input type="radio"
class="form-check-input" name="sex" value="1" checked>男
</div>
<div class="col-sm-1 form-check">
<input type="radio"
class="form-check-input" name="sex" value="0">女
</div>
</div>
</div>
<div class="mb-3">
<label for="message-text" class="col-form-label">爱好</label>
<div class="row">
<div class="col-sm-1 form-check">
<input class="form-check-input"
type="checkbox" id="check1"
name="option1"
value="1" checked>
<label class="form-check-label">打麻将</label>
</div>
<div class="col-sm-1 form-check">
<input class="form-check-input"
type="checkbox" id="check2"
name="option2"
value="2" checked>
<label class="form-check-label">打游戏</label>
</div>
<div class="col-sm-1 form-check">
<input class="form-check-input"
type="checkbox"
id="check3"
name="option3" value="3" checked>
<label class="form-check-label">喝酒</label>
</div>
<div class="mb-3">
<button type="button" class="btn btn-primary" onclick="onuser()">保持信息</button>
</div>
</div>
</div>
</form>
<script>
var $dateRange = $('#dateRange');
$dateRange.daterangepicker({
singleDatePicker:true,
showDropdowns:true,
format: "YYYY-MM-DD",
startDate: new Date()
});
function onuser(){
alert($("#userfrom").serialize());
$.ajax({
url: "/user/onsave",
type: "post",
data: $("#userfrom").serialize(),
dataType:"json",
success: function (data) {
alert(data);
}
})
}
</script>
- $(“#userfrom”).serialize() 将from内容转成JSON串。
From对应Pojo
Spring boot项目中创建一个Pojo类用于获得form中的表单内容,这里例如获得页面from中的name,deptid,sex三个属性信息内容。
public class UserPojo {
public String name;
public String deptid;
public String sex;
public String getDeptid() {
return deptid;
}
public void setDeptid(String deptid) {
this.deptid = deptid;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Controller容器获得页面from内容
创建一个Controller容器类,定义RequestMapping元素中的produces="application/json"属性表示对应ajax中的dataType:"json"获得信息是json串格式。如果ajax没有定义dataType:"json"就不需要定义produces="application/json"属性。
@ResponseBody 方法为返回ajax通信数据格式json。
@Controller()
public class UserController {
@RequestMapping(value = "/user/onsave"
,produces="application/json")
@ResponseBody
public String onsave(UserPojo para,
Model model) {
System.out.println(para.getSex()+" "+para.getDeptid()+" "+para.getName());
//返回添加成功标记
return "00";
}
页面中提交from的ajax请求部分
......
<script>
......
function onuser(){
$.ajax({
url: "/user/onsave",
type: "post",
data: $("#userfrom").serialize(),
dataType:"json",
success: function (data) {
alert(data);
}
})
}
</script>
Bootstrap-Validate验证
bootstrap-validate 原生的验证方法中form class=“was-validated” 必须在type=“submit” class="btn btn-primary"按钮中进行验证,验证成功后form刷新当前页面一次,对ajax提交方法不友好,需要进行大量二次修改。
默认验证方法
<form class="was-validated" id="userfrom" action="url">
<div class="mb-3">
<label for="message-text"
class="col-form-label">名称:</label>
<input type="text"
class="form-control"
id="name" required name="username"></input>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary">保持信息</button>
</div>
</div>
</form>
5.2 just-validate 验证表单
Just-validate 是一种无需依赖其他组件库就可以独立运行的一个验证组件库、基于 HTML5 数据属性的表单验证,同时支持客户端和服务器端表单验证,使用起来简单易懂。Just-validate特色是不需要在验证的元素html中设置验证属性内容,验证内容设置在组件的方法中,是页面的 html UI非常整洁。其他使用技巧参考官网Just-validate上的使用方法。
导入pom
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>just-validate</artifactId>
<version>3.8.1</version>
</dependency>
js引入
<script src="webjars/just-validate/3.8.1/dist/just-validate.production.min.js"></script>
表单验证例子
<form action="#" id="zhtform" autocomplete="off">
<div class="mb-3">
<label for="message-text"
class="col-form-label">名称:</label>
<input type="text"
class="form-control"
id="name"
autocomplete="off"
name="username"></input>
</div>
<div class="mb-3">
<label for="message-text"
class="col-form-label">mail:</label>
<input type="email"
class="form-control"
autocomplete="off" id="email" name="mail"/>
</div>
<div class="mb-3">
<label for="message-text"
class="col-form-label">年龄(20-100):</label>
<input type="number"
class="form-control"
id="age" autocomplete="off" name="age"/>
</div>
<div class="mb-3">
<label for="message-text"
class="col-form-label">日期:</label>
<input type="text" class="form-control"
id="dateRange" autocomplete="off"/>
</div>
<div class="mb-3">
<label for="message-text" class="col-form-label">备注:</label>
<textarea class="form-control" id="message-text"></textarea>
</div>
<div class="mb-3">
<label for="message-text" class="col-form-label">性别:</label>
<div class="row">
<div class="col-sm-1 form-check">
<input type="radio"
class="form-check-input" name="sex" value="1" checked>男
</div>
<div class="col-sm-1 form-check">
<input type="radio"
class="form-check-input" name="sex" value="0">女
</div>
</div>
</div>
</form>
<div class="mb-3">
<button onclick="onuser()" class="btn btn-primary">提交</button>
</div>
</form>
<script>
//验证表单组件
const validation = new JustValidate('#zhtform', {
errorFieldCssClass: 'is-invalid',
});
//验证表单元素设置
validation.addField('#name', [
{
rule: 'minLength',
value: 3,
errorMessage: '字符不可以小于3',
},
{
rule: 'required',
errorMessage: '名字不能为空',
},
{
rule: 'maxLength',
value: 30,
errorMessage: '字符不可以大于10',
},
])
.addField('#email', [
{
rule: 'required',
errorMessage: 'Email 不能为空',
},
{
rule: 'email',
errorMessage: 'Email 格式不对!',
},
])
.addField('#age', [
{
rule: 'customRegexp',
value: /^.{3,20}$/,
errorMessage: '年龄 字符长度在3-20之间',
},
]);
//验证表单元素设置
function onuser(){
validation.revalidate().then(isValid =>{
if(isValid){
//验证通过后提交数据
onSaveUser();
}
})
}
function onSaveUser(){
alert($("#zhtform").serialize());
$.ajax({
url: "/user/onsave",
type: "post",
data: $("#zhtform").serialize(),
dataType:"json",
success: function (data) {
alert(data);
}
})
}
</script>
- 1 创建一个验证组件JustValidate。
- 2 设置验证元素addField。
- 3 如果提交按钮在form 中,验证成功后运行.onSuccess(event)方法,如果提交按钮不在form 中需要自己定义事件触发validation.revalidate()方法。
<form action="#" id="zhtform">
<label for="name">用户名称</label>
<input
type="text"
class="form-control"
placeholder="用户名称"
autocomplete="off"
name="name"
id="name"
/>
<button class="btn btn-primary" id="submit-btn">Submit</button>
</form>
//验证表单组件
const validation = new JustValidate('#zhtform', {
errorFieldCssClass: 'is-invalid',
});
//验证表单元素设置
validation.addField('#name', [
{
rule: 'minLength',-------参考rule内容
value: 3,
errorMessage: '字符不可以小于3',---错误提示自己定义
}
]);
//验证
validation.revalidate().then(isValid =>{
if(isValid){
//验证通过后提交数据
}
})
rule 验证元素内容
则 | 描述 | 配置值格式 |
---|---|---|
required | 必填字段,不为空 | - |
email | 合法的邮件地址 | - |
minLength | 限制最小文本长度 | number |
maxLength | 限制最大文本长度 | number |
number | 值应该是一个数字 | - |
minNumber | 数字应大于定义值 | number |
maxNumber | 数字应小于定义值 | number |
password | 最少八个字符,至少一个字母和一个数字 | - |
strongPassword | 最少 8 个字符,至少 1 个大写字母、1 个小写字母、1 个数字和 1 个特殊字符 | - |
customRegexp | 自定义正则表达式 | Regexp |
minFilesCount | 上传文件数应大于定义值 | number |
maxFilesCount | 上传的文件数应小于定义的值 | number |
files | 上传的文件属性应该是有效的,基于值配置(在文件验证部分阅读更多内容) | files: { extensions?: string[]; types?: string[]; minSize?: number; maxSize?: number; names?: string[]; } |
just-validate方法
验证通过时回调。
.onSuccess(event)
验证失败时回调。
.onFail(fields)
重新验证字段,手动触发字段验证的方法。返回一个带有布尔值的承诺 - 有效/无效字段。
.revalidateField(field: string).then(isValid => {})
重新验证
.revalidate().then(isValid => {})
刷新整个表单的方法 - 字段设置
.refresh()
销毁
.destroy()
删除字段中的验证规则
.removeField(field: string)
5.3 OctaValidate 验证表单
最新出的一个开源的表单验证库,它的特点是小巧而且功能丰富,使用起来容易上手,它是本人比较喜欢用的一种表单验证插件。它和just-validate是二个完全不同风格的验证库,just-validate是通过组件方法定义验证字段的验证规则,OctaValidate则是在验证字段的html UI元素中设置验证规则,比较接近Bootstrap-Validate原生的验证方法,它弥补了Bootstrap-Validate中的一些缺陷使用起来更加的方便。OctaValidate官网地址需要手动下载JS到项目中,因为OctaValidate是最新出来组件库在webjars中还没有它的包。
例子代码
//导入OctaValidate库
<script src="js/validate.js"></script>
<form action="#" id="zhtOform" novalidate>
<div class="mb-3">
<label for="message-text"
class="col-form-label">名称:</label>
<input type="text"
class="form-control"
id="inp_name"
octavalidate="R"
ov-required:msg="名字必须填写"
length="6"
ov-length:msg="必须是6个字符"
name="username"></input>
</div>
<div class="mb-3">
<label for="message-text"
class="col-form-label">密码:</label>
<input type="password"
class="form-control"
name="paw"
id="inp_reg_pwd" octavalidate="R,PASS"
ov-required:msg="密码必须填写"
maxlength="10"
ov-maxlength:msg="长度不能大于10个字符"
minlength="6"
ov-minlength:msg="长度不能小于6个字符"/>
</div>
<div class="mb-3">
<label for="message-text"
class="col-form-label">密码验证:</label>
<input type="password"
class="form-control"
id="inp_reg_pwd2" equalto="inp_reg_pwd"
ov-equalto:msg="两次密码不一样" />
</div>
<div class="mb-3">
<label for="message-text"
class="col-form-label">工资:</label>
<input type="number"
class="form-control"
id="gz" octavalidate="R,GZ"
ov-required:msg="工资必须填写" />
</div>
</form>
<div class="mb-3">
<button onclick="onVil()" class="btn btn-primary">提交</button>
</div>
</form>
<script>
let zvForm = new octaValidate('zhtOform', {
strictMode : true,
strictWords : ["null", "empty", "undefined", "NaN"]
});
//自定义正则验证规则 GZ 在octavalidate="GZ“ 使用
zvForm.customRule('GZ', /^(([1-9]{1}\d*)|(0{1}))(\.\d{1,2})?$/, '格式必须是 #.00 后两位');
function onVil(){
//正则验证通过
if(zvForm.validate()){
//提交表单
}
}
</script>
-
在input 元素中定义 octavalidate="验证规则“ ,ov-equalto:msg中定义错误提示。
-
长度验证`maxlength, minlength,length 三个默认属性设置。
maxlength="10" ov-maxlength:msg="长度不能大于10个字符" minlength="6" ov-minlength:msg="长度不能小于6个字符" length="6" ov-length:msg="必须是6个字符"
OctaValidate 默认验证规则表
Rule名称 | 说明 | 错误提示 |
---|---|---|
R | Required (不能为空) | ov-required:msg |
EMAIL(email格式) | ov-email:msg | |
ALPHA_ONLY | 仅限字母 | ov-alpha-only:msg |
ALPHA_SPACES | 字母和空格 | ov-alpha-spaces:msg |
ALPHA_NUMERIC | 带数字的字母 | ov-alpha-numeric:msg |
LOWER ALPHA | 小写字母 | ov-lower-alpha:msg |
UPPER_ALPHA | 大写字母 | ov-upper-alpha:msg |
PWD | 密码 | ov-pwd:msg |
DIGITS | 数字或数字 | ov-digits:msg |
URL | 网址 | ov-url:msg |
URL_QP | 带有查询参数的 URL | ov-url-qp:msg |
DATE_MDY | 日期格式为 MM/DD/YYYY | ov-date-mdy:msg |
USERNAME | 用户名 | ov-username:msg |
TEXT | 一般文本 | ov-text:msg |
规则使用例子
octavalidate 元素中定义要验证的规则
ov-required:msg 定义错误提示
<input id="inp_uname"
type="text"
octavalidate="R,USERNAME"
ov-username:msg="必须填写用户名字"/>
<input type="password"
class="form-control"
name="paw"
id="inp_reg_pwd"
octavalidate="R,PASS"
ov-required:msg="密码必须填写"/>
常用API方法
// 验证表单
formVal.validate();
// 检查表单状态
formVal.status();
// 返回表单ID
formVal.form();
// 添加更多自定义规则
formVal.moreCustomRules(RULES);
// 返回库版本
formVal.version();
//自定义正则验证规则 GZ 在octavalidate="GZ“ 使用
//这个方法很主要 定义自己的验证规则,弥补组件中默认规则不全
zvForm.customRule('GZ', /^(([1-9]{1}\d*)|(0{1}))(\.\d{1,2})?$/, '格式必须是 #.00 后两位');
6 提示框
系统提示可以选项Bootstrap 5中的组件,也可以选择iziToast组件。下面介绍的iziToast使用方法。
- iziToast - 提示框使用 toast 的 JavaScript 库。
导入提示框的pom
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>izitoast</artifactId>
<version>1.4.0</version>
</dependency>
在页面中定义提示框应用
<script src="webjars/izitoast/1.4.0/dist/js/iziToast.min.js"></script>
<link rel="stylesheet" href="webjars/izitoast/1.4.0/dist/css/iziToast.min.css"/>
例子
<div class="container">
<form method="post" >
<div class="row">
<div class="col ">
<button class="btn btn-primary" type="submit">查询</button>
</div>
</div>
</form>
</div>
</div>
<script>
$('button[type="submit"]').click(function (event) {
event.preventDefault();
iziToast.show({
title: '提示',
message: '查询成功',
position: 'topRight',
timeout: 500000,
color: 'green'
});
});
</script>
7 弹出框
弹出框是系统开发中最常使用功能组件之一。这里介绍了bootstrap自带和bootstrap-modbox 组件。
7.1 bootstrap自带模态弹出功能
弹出框无需导入其他的js,可以使用Bootstrap5中的Modal组件。使用方法是在弹出框元素上设置data-toggle="modal"
属性。例如 按钮组件,或者其他引用组件中设置data-target="#foo"
或href="#foo"
后引用组件变成为弹出框这种特定模式,可以与弹出目标进行切换。
<button type="button"
class="btn btn-primary"
data-bs-toggle="modal"
data-bs-target="#exampleModal" -----| exampleModal按钮弹出对象
data-id="0">添加</button> |
<div class="modal fade" |
id="exampleModal" <--------------|
aria-labelledby="exampleModalLabel"<---|按钮弹设置弹出
tabindex="-1"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">添加信息</h5>
<button type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
<form>
<div class="mb-3">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button"
class="btn btn-secondary"
data-bs-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary">
添加
</button>
</div>
</div>
</div>
</div>
<script>
//获得弹出框引用
var exampleModal = document.getElementById('exampleModal');
//监听这个弹出框的弹出行为
exampleModal.addEventListener('show.bs.modal', function (e) {
var btn = $(e.relatedTarget);
// 获得这个弹出框的id值 添加按钮中元素 data-id="0"
// 例如:data-name 引用为btn.data("name")
// Modal使用 data-属性名称 方法传值
alert(btn.data("id"));
})
</script>
- modal 传递数据的方式是在事件触发元素中加入 data- 属性名称=值。
<button type="button"
data-bs-target="#zhtModal" zhtModal弹出框组件引用
data-id="0" ------创给弹出框组件参数
data-name="zhtbs" ------创给弹出框组件参数
data-deptid="100" ------创给弹出框组件参数
>添加</button>
- 在js 脚本中的获得modal 事件e.relatedTarget属性,通过relatedTarget来获得传值内容。
<button type="button"
class="btn btn-primary"
data-bs-toggle="modal"
data-bs-target="#exampleModal" -----| exampleModal按钮弹出对象
data-id="0"
data-name="zhtbs" ------创给弹出框组件参数
data-deptid="100" ------创给弹出框组件参数
>添加</button>
exampleModal.addEventListener('show.bs.modal', function (e) {
var btn = $(e.relatedTarget);
btn.data("id")//获得data-id
btn.data("name")//获得data-name
btn.data("deptid")//获得data-deptid
})
7.2 bootstrap-modbox 使用
bootstrap自带的ui弹出框使用起来有一些不方便和复杂,需要在项目中导入bootstrap-modbox插件来完成一些弹出框扩展。
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>bootstrap-modbox</artifactId>
<version>1.6.2</version>
</dependency>
spring boot项目中引入bootstrap-modbox
<script src="webjars/bootstrap-modbox/1.6.2/dist/bootstrap-modbox.js"></script>
弹出框基本操作
<div class="row">
<div class="col ">
<button class="btn btn-primary"
type="button"
onclick="alert1()">modbox alert1</button>
<button class="btn btn-primary"
type="button"
onclick="alert2()">modbox alert2</button>
<button class="btn btn-primary"
type="button"
onclick="alert3()">info</button>
<button class="btn btn-primary"
type="button"
onclick="alert4()">success</button>
<button class="btn btn-primary"
type="button"
onclick="alert5()">error</button>
<button class="btn btn-primary"
type="button"
onclick="confirm()"> confirm</button>
</div>
</div>
<script>
function alert1(){
modbox.alert('提示信息');
}
function alert2(){
modbox.alert({
title: '提示标题',
body: '提示信息',
closeButton: {
label: '关闭'
}
});
}
function alert3(){
modbox.info({
title: '提示标题',
body: '提示信息',
closeButton: {
label: '关闭'
}
});
}
function alert4(){
modbox.success({
title: '提示标题',
body: '提示信息',
closeButton: {
label: '关闭'
}
});
}
function alert5(){
modbox.error({
title: '提示标题',
body: '提示信息',
closeButton: {
label: '关闭'
}
});
}
function confirm(){
modbox.confirm({
body: '是否要删除',
okButton: {
label: '确定',
size: 'lg'
},
closeButton: {
label: '取消',
size: 'sm'
}
})
.then(() =>{alert("点击确定事件");})
.catch(() => {alert("取消");});
}
</script>
Alert 例图
confirm例图
bootstrap-modbox组件中属性定义在json中,以下为modbox中的属性内容。开发者可以根据属性的参数,来定义自己的弹出框。
bootstrap-modbox参数与方法
// 自定义图标类
icon: null,
// 颜色基于 Bootstrap 实用程序类
style: 'white',
// 标题文本颜色
titleStyle: null,
// 对话框标题
title: '标题内容',
// 对话框内容
正文: '' ,
// 替代正文配置选项
message: '',
// sm, lg, 大小 参照bootstrap
size: null,
// 将弹出框
居中 center: false,
// 启用淡入淡出动画
fade: true,
// 显示页面加载时弹出框
show: false,
// 在标题中显示关闭按钮
showHeaderClose: true,
// 在传递给显示和显示的事件回调函数的事件对象上设置relatedTarget 属性。
// 可以在调用 .show() 方法时通过传入一个元素来覆盖。
relatedTarget: undefined,
// 可滚动
scrollable: true,
// 关闭时销毁弹出框
destroyOnClose: false,
// 向弹出框添加默认按钮
defaultButton: true,
// 交换按钮顺序
swapButtonOrder: false,
// start, end, center, between, around,
evenly justifyButtons: null,
// 事件
events: {
show: null,
shown: null,
hide: null,
hidden: null,
hidePrevented: null,
},
// 仅适用于构造函数模式
按钮:[],
// 仅适用于类模式,并覆盖 modbox.defaultButtonOptions 设置的默认值
okButton: {
label: 'OK',
style: 'primary'
},
closeButton: {
label: ' Cancel',
style: 'secondary'
},
// 仅适用于 .prompt() class modal
input: {
type: 'text',
class: '',
value: '',
title: null,
placeholder: null,
autocomplete: 'off',
minlength: null,
maxlength: null,
pattern: null,
required: false,
sanitizer: false, // 如果为 true,则在传递给 Promise 解析函数之前,将使用为 modal sanitizer 选项定义的相同函数对输入字段值进行清理。或者,可以提供一个单独的函数,这与 modal 选项不同。
},
-------------- modbox定义方法 --------------
// 添加一个新按钮
// addButton(options, swapOrder)
instance.addButton({
label: 'New Button'
});
// 调度一个事件
// addEvent(event, function)
instance.addEvent('shown', () => console.log('shown'));
// 显示弹出框
instance.show(relatedTarget);
// 隐藏弹出框
instance.hide();
// 切换弹出框
instance.toggle();
// 处理弹出框
instance.dispose();
// 销毁实例
instance.destroy();
// 重新定位弹出框
instance.handleUpdate();
// 设置默认值
instance.setDefaults(string modalType, object modalOptions);
自定义弹出框定义
<button class="btn btn-primary"
type="button" onclick="usernew()">自定义弹出框</button>
<script>
const myModal = new modbox({
id: 'myModal',
style: 'primary',
title: '添加人员信息',
body: '<div id="zhtbs"></div>',
justifyButtons: 'between',
destroyOnClose: false,
buttons: ['<button type="button" class="btn btn-dark" data-bs-dismiss="modal" οnclick="onsave()">保存</button>'],
events: {
shown: () =>{alert('页面初始化');}
}
});
myModal.addButton({ label: '关闭', style: 'danger' }, true);
myModal.addEvent('hidden', () => {alert("关闭弹出框");});
//初始化弹出框
function usernew(){
myModal.show();
$('#zhtbs').html('欢迎来到韬哥的代码世界');
}
function onsave(){
myModal.hide();
}
</script>
可以使用Jquery.ajax方法访问SpringBoot项目中的Thymeleaf模板页面,通过requer获得Thymeleaf模板页面中的HTML字符串,将获得到的html字符串在通过$(‘#’).find(‘.modal-body’).html(data);方法写入到Modal弹出属性元素中。
<script>
const zhtmodal = new modbox({
id: 'zhtmodal',
style: 'primary',
title: '添加人员信息',
body: '<div id="zhtbs"></div>',
justifyButtons: 'between',
destroyOnClose: false,
buttons: ['<button type="button" class="btn btn-dark" οnclick="onsaveuser()">保存</button>','<button type="button" class="btn btn-danger" οnclick="onuserclose()">关闭</button>'
]
});
//初始化页面 通过rul /user/initSave获得用户添加页面的html字符串
function onzht(){
zhtmodal.show();
$.get("/user/initSave", function (data) {
$('#zhtmodal').find('.modal-body').html(data);
});
}
function onuserclose(){
zhtmodal.hide();
}
//添加用户信息提交数据
function onsaveuser(){
alert($("#userfrom").serialize());
$.ajax({
url: "/user/onsave",
type: "post",
data: $("#userfrom").serialize(),
dataType:"json",
success: function (data) {
alert(data);
zhtmodal.hide();
}
})
}
</script>
7.3 bootstrap-modbox 抽屉
自己增加一些css样式来把bootstrap-modbox弹出框改成抽屉弹出框模式。
加入css
<style>
.right .modal-dialog,
.left .modal-dialog {
transition: transform .25s ease-out;
position: fixed;
margin: auto;
height: 100%;
}
.modal.right .modal-content,
.modal.left .modal-content {
overflow-y: auto;
border-radius: 0;
border: none;
height: 100%;
}
.right .modal-dialog {
transform: translateX(50px);
right: 0;
}
.left .modal-dialog {
transform: translateX(-50px);
left: 0;
}
</style>
js例子
<button class="btn btn-primary" type="button" onclick="onzct()">弹出框抽屉框</button>
<script>
const zhtmodal = new modbox({
id: 'zhtmodal',
style: 'primary',
title: '添加人员信息',
body: '',
justifyButtons: 'between',
scrollable:false,
destroyOnClose: false,
buttons: ['<button type="button" class="btn btn-dark" οnclick="onsaveuser()">保存 '<button type="button" class="btn btn-danger" onclick="onuserclose()">关闭</button>'
]
});
function onzct(){
//抽屉css样式加入 大抽屉
$('#zhtmodal').find('.modal-dialog').addClass('modal-lg w-100');
//抽屉css样式加入 抽屉方向
$('#zhtmodal').addClass('right');
zhtmodal.show();
$.get("/user/userO", function (data) {
$('#zhtmodal').find('.modal-body').html(data);
});
}
</script>
css样式使用bootstrap中的css,例如大小用的是modal-lg,modal-sm
//大抽屉
$('#zhtmodal').find('.modal-dialog').addClass('modal-lg w-100');
//小抽屉
$('#zhtmodal').find('.modal-dialog').addClass('modal-sm w-100');
//方向 left right |
$('#zhtmodal').addClass('right');-| |
| |
<div class="modal left"> <------| |
<div class="modal-dialog modal-sm w-100"> <---|
</div>
</div>
自定义抽屉组件
作者还提供了一套自己写的抽屉组件放在代码项目中,使用起来很方便二次扩展性也是非常强。抽屉组件代码放在吗项目中可以下载查看。
<link rel="stylesheet" href="css/drawer.css"/>
<script src="js/zhtdrawer.js"></script>
<button class="btn btn-primary"
type="button"
οnclick="onzhtct()"
data-drawer-trigger //弹出
aria-controls="drawer-zht">zht抽屉框</button>
| 两个id对应
<section id="drawer-zht" class="drawer drawer--left" data-drawer-target>
<div class="drawer__overlay" tabindex="-1"></div>
<div class="drawer__wrapper">
<div class="drawer__header">
<div class="drawer__title">
标题部分
</div>
<button class="drawer__close"
data-drawer-close //关闭窗体
aria-label="Close Drawer"></button>
</div>
<div class="drawer__content" id="drawer__content">
业务内容量
</div>
</div>
</section>
<script>
function onzhtct(id){
alert(id);
$.get("/user/userO", function (data) {
//设置内容
$('#drawer__content').html(data);
});
}
</script>
事件参数
弹出窗体设置都是在html 元素中设置对应属性
<button class="btn btn-primary"
type="button"
onclick="onzhtct(40)"
data-drawer-trigger ----- 触发按钮为弹出窗体
aria-controls="drawer-zht">zht抽屉框</button>
窗体关闭
<button class="btn btn-primary"
type="button"
data-drawer-close ----- 关闭窗体
>关闭</button>
系列文章目录
【Springboot 入门培训 】#1 MyBatis项目运行环境配置
【Springboot 入门培训 】#2 MyBatis 增改删除与查询 in like foreach操作
【Springboot 入门培训 】#3 MyBatis 多数据源与缓存和数据连接池设置
【Springboot 入门培训 】#4 WEB+JSP MVC项目搭建
【Springboot 入门培训 】#5 WEB+Thymeleaf MVC项目搭建与测试
【Springboot 入门培训 】#6 (Framework7 移动 webapp) WEB APP 项目搭建
【Springboot 入门培训 】#7 (Framework7 移动webapp) 页面路由跳转
【Springboot 入门培训 】#8 (Framework7 移动webapp) Component 模板MVVM与AJAX
【Springboot 入门培训 】# 9 Security(一) 登录验证初始化
【Springboot 入门培训 】#10 Security(二) 数据库DB 登录验证
【Springboot 入门培训 】#11 Security(三) json 前后端分离跨域登录
【Springboot 入门培训 】#12 Security(四) Jwt 前后端分离跨域登录
【Springboot 入门培训 】#13 Security(五) oauth2 基础应用
【Springboot 入门培训 】#14 WebJars 样式包BootStrap 5架构
【Springboot 入门培训 】#15 MyBatis-Thymeleaf 插件在项目中的应用
【Springboot 入门培训 】#16 Spring boot 日志 Slf4j + Logback
【Springboot 入门培训 】#17 WebJars + BootStrap5 常用JS组件应用
【Springboot 入门培训 】#18 SpringBoot Cache 缓存实现
Spring boot 中Thymeleaf 模板 html 标签使用