layui的穿梭框本身不复杂,一个简单的穿梭框代码如下:
transfer.render({
elem: ‘#text1‘
,data: [
{"id": "1", "name": "李白"}
,{"id": "2", "name": "杜甫"}
,{"id": "3", "name": "贤心"}
]
,value:[1] //右侧数据
,parseData: function(res){
return {
"value": res.id //数据值
,"title": res.name //数据标题
,"disabled": res.disabled //是否禁用
,"checked": res.checked //是否选中
}
}
});
难点在于官网没有对data的动态获取进行介绍,开始我以为transfer.render和table.render都可以url进行动态获取,后来发现,transfer.render没有url这个参数,好在data可以用 " data:变量 " 的形式传递,这样一来我们可以用ajax取得数据赋值给变量,再把变量赋值给data进行渲染,这里的要点之一是data的数据格式是个列表:
[{"value": "1", "title": "李白", "disabled": "", "checked": ""}]
还有就是,默认选中框value的数据是数组:[1],这个数组的值默认是data的value(你可以把其他数据用parsedata转化为value,title是显示的数据)
如此一来,一个通过ajax取数据的穿梭框代码如下:
$(function() {layui.use(‘transfer‘, function(){
var transfer = layui.transfer;
var old_group =$("input[name=‘old_group_name‘]").val();
var data1
$.ajax({
data:{"old_group_name":old_group},
url:"getGroupUseNode",
type:"POST",
dataType:"json",
success:function (arg) {
data1=arg.data
{#console.log(data1)#}
//渲染
transfer.render({
elem: ‘#transfer‘ //绑定元素
,data:data1
,title:["现有节点","在使用节点"]
,value:arg.value
,id: ‘demo1‘ //定义索引
,parseData: function(res){
return {
"value": res.id //数据值
,"title": res.node_ip //数据标题
,"disabled": res.disabled //是否禁用
,"checked": res.checked //是否选中
}
}
});
}
})
});
})
这里踩了个坑,js一直获取不到父页面返回的数据,所以用$(function(){}包裹处理ajax函数,success后通过服务端取得的数据对穿梭框进行赋值
服务端view处理函数如下:
def getGroupUseNode(request):
group_name=request.POST.get(‘old_group_name‘)
node_all=Node.objects.all().values("id","node_ip")
use_node=Node.objects.filter(node_group__Group=group_name).values_list("id")
GroupUseNode={ }
GroupUseNode["data"]=list(node_all)
GroupUseNode["value"]=list(use_node)
print(json.dumps(GroupUseNode))
return HttpResponse(json.dumps(GroupUseNode))
由此,根据上面的增删改查和穿梭框的使用,写成了节点分组管理,主要代码如下:
goupControl.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>layui</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="/static/lib/layui-v2.6.3/css/layui.css" media="all">
<link rel="stylesheet" href="/static/css/public.css" media="all">
</head>
<body>
<div class="layuimini-container">
<div class="layuimini-main">
<fieldset class="table-search-fieldset">
<legend>搜索信息</legend>
<div style="margin: 10px 10px 10px 10px">
<form class="layui-form layui-form-pane" action="">
<div class="layui-form-item">
<select name="" id="">状态:
<option value="">全部</option>
<option value="">使用中</option>
<option value="">暂停使用</option>
</select>
<div class="layui-inline">
<label class="layui-form-label">节点名称</label>
<div class="layui-input-inline">
<input type="text" name="search_node_name" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">使用分组</label>
<div class="layui-input-inline">
<input type="text" name="classify" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="data-search-btn"><i class="layui-icon"></i> 搜 索</button>
</div>
</div>
</form>
</div>
</fieldset>
<script type="text/html" id="toolbarDemo">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn" lay-event="add"> 添加 </button>
<button class="layui-btn layui-btn-sm layui-btn-danger data-delete-btn" lay-event="delete"> 删除 </button>
</div>
</script>
<table class="layui-hide" id="currentTableId" lay-filter="currentTableFilter"></table>
<script type="text/html" id="currentTableBar">
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-xs layui-btn-danger data-count-delete" lay-event="delete">删除</a>
</script>
</div>
</div>
<script src="/static/lib/jquery-3.4.1/jquery-3.4.1.min.js"></script>
<script src="/static/lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
<script>
layui.use([‘form‘, ‘table‘], function () {
var $ = layui.jquery,
form = layui.form,
table = layui.table;
table.render({
elem: ‘#currentTableId‘,
toolbar: ‘#toolbarDemo‘,
url:‘getGroupList‘,
method: ‘get‘,
defaultToolbar: [‘filter‘, ‘exports‘, ‘print‘, {
title: ‘提示‘,
layEvent: ‘LAYTABLE_TIPS‘,
icon: ‘layui-icon-tips‘
}],
cols: [[
{type: "checkbox", width: 50},
{field: ‘id‘, width: 80, title: ‘ID‘, sort: true},
{field: ‘group_name‘, width: 180, title: ‘分组名‘},
{field: ‘remark‘, width: 180, title: ‘备注‘,},
{title: ‘操作‘, minWidth: 150, toolbar: ‘#currentTableBar‘, align: "center"}
]],
limits: [10, 15, 20, 25, 50, 100],
limit: 15,
page: true,
skin: ‘line‘,
request: {
pageName: ‘curr‘ //页码的参数名称,默认:page
,limitName: ‘nums‘ //每页数据量的参数名,默认:limit
}
});
// 监听搜索操作
form.on(‘submit(data-search-btn)‘, function (data) {
var result = JSON.stringify(data.field);
layer.alert(result, {
title: ‘最终的搜索信息‘
});
//执行搜索重载
table.reload(‘currentTableId‘, {
page: {
curr: 1
}
, where: {
searchParams: result
}
}, ‘data‘);
return false;
});
/**
* toolbar监听事件
*/
table.on(‘toolbar(currentTableFilter)‘, function (obj) {
if (obj.event === ‘add‘) { // 监听添加操作
var index = layer.open({
title: ‘添加节点‘,
type: 2,
shade: 0.2,
maxmin:true,
shadeClose: true,
area: [‘100%‘, ‘100%‘],
content: ‘addGroup‘,
end:function () {
table.reload(‘currentTableId‘, {url:‘getGroupList‘})
}
});
$(window).on("resize", function () {
layer.full(index);
});
} else if (obj.event === ‘delete‘) { // 监听删除操作
var checkStatus = table.checkStatus(‘currentTableId‘)
, data = checkStatus.data;
{#layer.alert(JSON.stringify(data));#}
var group=new Array();
for (i=0;i<data.length;i++)
{
group[i]=data[i]["group_name"]
}
layer.confirm(‘删除分组‘+group+‘?‘, function (index) {
$.ajax({
data:{‘group_name‘:group.toString()},
url:"delGroup",
type:"POST",
dataType:"json",
success:function (arg) {
if(arg.status=="ok"){
table.reload(‘currentTableId‘, {url:‘getGroupList‘})
layer.close(index);
}
else{
console.log(arg.msg)
}
}
})
});
}
});
//监听表格复选框选择
table.on(‘checkbox(currentTableFilter)‘, function (obj) {
console.log(obj)
});
table.on(‘tool(currentTableFilter)‘, function (obj) {
var data = obj.data;
if (obj.event === ‘edit‘) {
{#console.log(data)#}
var index = layer.open({
title: ‘编辑用户‘,
type: 2,
shade: 0.2,
maxmin:true,
shadeClose: true,
area: [‘100%‘, ‘100%‘],
content: ‘editGroup‘,
success: function (layero, index) {
{#var body = layer.getChildFrame(‘body‘, index)#}
{#body.find("input[name=‘old_group_name‘]").text(data.group_name)#}
{#body.find("input[name=‘group_name‘]").val(data.group_name)#}
{#body.find("textarea[name=‘remark‘]").val(data.remark)#}
{# 子页面重新渲染 #}
var iframeWindow = layero.find(‘iframe‘)[0].contentWindow;
iframeWindow.child(data)
iframeWindow.layui.form.render();
},
end:function () {
table.reload(‘currentTableId‘, {url:‘getGroupList‘})
}
});
$(window).on("resize", function () {
layer.full(index);
});
return false;
} else if (obj.event === ‘delete‘) {
layer.confirm(‘真的删除行么‘, function (index) {
$.ajax({
data:{‘group_name‘:obj.data["group_name"]},
url:"delGroup",
type:"POST",
dataType:"json",
success:function (arg) {
if(arg.status=="ok"){
obj.del();
layer.close(index);
}
else{
console.log(arg.msg)
}
}
})
});
}
});
});
</script>
</body>
</html>
这里的父页面传值采取了跟上篇不一样的做法,上一篇是父页面获取子页面的body,通过body查找元素赋值,这里是父页面执行子页面函数,子页面函数查找本页面元素赋值
edit.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>layui</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="/static/lib/layui-v2.6.3/css/layui.css" media="all">
<link rel="stylesheet" href="/static/css/public.css" media="all">
<style>
body {
background-color: #ffffff;
}
.err{
color: red;
}
</style>
</head>
<body>
<div class="layui-form layuimini-form">
<div class="layui-form-item">
<label class="layui-form-label required">节点ip</label>
<div class="layui-input-block">
<span class="node_ip_err err" ></span>
<input style="display: None" name="old_group_name" >
<input type="text" name="group_name" lay-verify="required" lay-reqtext="分组名不能为空" placeholder="请输入分组名" value="" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">备注信息</label>
<div class="layui-input-block">
<textarea name="remark" class="layui-textarea" placeholder="请输入备注信息"></textarea>
</div>
</div>
<div style="margin-left: 180px" class="layui-form-item">
<div id="transfer" class="demo-transfer" ></div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
</div>
</div>
</div>
</div>
<script src="/static/lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
<script src="/static/lib/jquery-3.4.1/jquery-3.4.1.min.js"></script>
<script>
function child(data){
$("input[name=‘old_group_name‘]").val(data.group_name)
$("input[name=‘group_name‘]").val(data.group_name)
$("textarea[name=‘remark‘]").val(data.remark)
//console.log($("input[name=‘old_group_name‘]").val())
}
$(function() {layui.use(‘transfer‘, function(){
var transfer = layui.transfer;
var old_group =$("input[name=‘old_group_name‘]").val();
var data1
$.ajax({
data:{"old_group_name":old_group},
url:"getGroupUseNode",
type:"POST",
dataType:"json",
success:function (arg) {
data1=arg.data
{#console.log(data1)#}
//渲染
transfer.render({
elem: ‘#transfer‘ //绑定元素
,data:data1
,title:["现有节点","在使用节点"]
,value:arg.value
,id: ‘demo1‘ //定义索引
,parseData: function(res){
return {
"value": res.id //数据值
,"title": res.node_ip //数据标题
,"disabled": res.disabled //是否禁用
,"checked": res.checked //是否选中
}
}
});
}
})
});
})
layui.use([‘form‘], function () {
var form = layui.form,
layer = layui.layer,
$ = layui.$;
//监听提交
form.on(‘submit(saveBtn)‘, function (data) {
var transfer = layui.transfer;
var getData = transfer.getData(‘demo1‘);
postdata=data.field
postdata["use_node"]=JSON.stringify(getData)
var index = layer.alert(JSON.stringify(postdata), {
title: ‘最终的提交信息‘
}, function () {
// 关闭弹出层
$.ajax({
data:postdata,
url:"editGroup",
type:"POST",
dataType:"json",
success:function (arg) {
console.log(arg)
if(arg.status == "ok"){
layer.close(index);
var iframeIndex = parent.layer.getFrameIndex(window.name);
parent.layer.close(iframeIndex);
}else {
var err=arg.msg
for ( x in err)
{
$("."+x+"_err").text(err[x])
}
}
}
})
});
return false;
});
});
</script>
</body>
</html>
值得一提的是,穿梭框是通过elem: ‘#transfer‘绑定到对应元素的,由此可以设定div的位置
addGroup.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>layui</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="/static/lib/layui-v2.6.3/css/layui.css" media="all">
<link rel="stylesheet" href="/static/css/public.css" media="all">
<style>
body {
background-color: #ffffff;
}
.err{
color: red;
}
</style>
</head>
<body>
<div class="layui-form layuimini-form">
<div class="layui-form-item">
<label class="layui-form-label required">节点ip</label>
<div class="layui-input-block">
<span class="node_ip_err err" ></span>
<input type="text" name="node_ip" lay-verify="required" lay-reqtext="节点ip不能为空" placeholder="请输入节点ip" value="" class="layui-input">
<tip>填写节点ip</tip>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">开关</label>
<div class="layui-input-block">
<input type="radio" name="work_or_no" value="1" title="开" checked="">
<input type="radio" name="work_or_no" value="0" title="关">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">备注信息</label>
<div class="layui-input-block">
<textarea name="remark" class="layui-textarea" placeholder="请输入备注信息"></textarea>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
</div>
</div>
</div>
<script src="/static/lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
<script src="/static/lib/jquery-3.4.1/jquery-3.4.1.min.js"></script>
<script>
layui.use([‘form‘], function () {
var form = layui.form,
layer = layui.layer,
$ = layui.$;
//监听提交
form.on(‘submit(saveBtn)‘, function (data) {
var index = layer.alert(JSON.stringify(data.field), {
title: ‘最终的提交信息‘
}, function () {
// 关闭弹出层
$.ajax({
data:data.field,
url:"addNode",
type:"POST",
dataType:"json",
success:function (arg) {
if(arg.status == "ok"){
layer.close(index);
var iframeIndex = parent.layer.getFrameIndex(window.name);
parent.layer.close(iframeIndex);
}else {
var err=arg.msg
for ( x in err)
{
$("."+x+"_err").text(err[x])
}
}
}
})
{#layer.close(index);#}
{##}
{#var iframeIndex = parent.layer.getFrameIndex(window.name);#}
{#parent.layer.close(iframeIndex);#}
});
return false;
});
});
</script>
</body>
</html>
服务端处理函数:
from django.shortcuts import render,HttpResponse,redirect
from database.models import *
from tools.pager import *
import json,copy,re
from tools.forms_tpl import *
def groupControl(request):
ret=render(request,"groupControl.html")
ret["X-Frame-Options"]="sameorigin"
return ret
def getGroupList(request):
currentPage=int(request.GET.get("curr"))
dataCount=int(Group.objects.all().count())
perPageCount=int(request.GET.get("nums"))
page_obj = Pagination(dataCount=dataCount, currentPage=currentPage, perPageCount=perPageCount)
data_start = page_obj.data_start()
data_end = page_obj.data_end()
Grouplist={
"code": 0,
"msg": "",
"count": dataCount,
"data": []
}
Group_obj=list(Group.objects.all()[data_start:data_end].values())
Grouplist["data"]=Group_obj
return HttpResponse(json.dumps(Grouplist))
def addGroup(request):
if request.is_ajax():
print(request.POST)
ajax_rsp = {"status": "err", "msg": None}
NewGroup=Groupform(data=request.POST)
if NewGroup.is_valid():
print(NewGroup.cleaned_data)
Group.objects.create(**NewGroup.cleaned_data)
ajax_rsp["status"]="ok"
else:
ajax_rsp["msg"] = NewGroup.errors
print(NewGroup.errors)
return HttpResponse(json.dumps(ajax_rsp))
ret=render(request,"addGroup.html")
ret["X-Frame-Options"]="sameorigin"
return ret
def delGroup(request):
if request.is_ajax():
GroupArray=re.split(‘,‘,request.POST.get("group_name"))
ajax_rsp={"status":"err","msg":None}
try:
for group in GroupArray:
Group.objects.filter(group_name=group).delete()
ajax_rsp["status"]= "ok"
except Exception as e:
ajax_rsp["msg"]=str(e)
return HttpResponse(json.dumps(ajax_rsp))
return HttpResponse("ok")
#
#
def editGroup(request):
if request.is_ajax():
# 取出新的ip id值列表
node=[]
for item in json.loads(request.POST.get("use_node")):
node.append(str(item[‘value‘]))
print(node)
postdata=copy.deepcopy(request.POST)
ajax_rsp = {"status": "err", "msg": None}
old_Group_name = request.POST.get("old_group_name")
new_Group_name = request.POST.get("group_name")
NewGroup=GroupRegform(data=request.POST)
if NewGroup.is_valid():
print(NewGroup.cleaned_data)
Group.objects.filter(group_name=old_Group_name).delete()
Group.objects.create(**NewGroup.cleaned_data)
Group.objects.filter(group_name=old_Group_name).update(**NewGroup.cleaned_data)
NewGroup_obj=Group.objects.filter(group_name=new_Group_name).first()
node_obj=Node.objects.filter(id__in=node)
for obj in node_obj:
Node_Group.objects.create(Group=NewGroup_obj,Node=obj)
ajax_rsp["status"]="ok"
else:
ajax_rsp["msg"] = NewGroup.errors
return HttpResponse(json.dumps(ajax_rsp))
ret = render(request, "editGroup.html")
ret["X-Frame-Options"] = "sameorigin"
return ret
def getGroupUseNode(request):
group_name=request.POST.get(‘old_group_name‘)
node_all=Node.objects.all().values("id","node_ip")
use_node=Node.objects.filter(node_group__Group=group_name).values_list("id")
GroupUseNode={ }
GroupUseNode["data"]=list(node_all)
GroupUseNode["value"]=list(use_node)
print(json.dumps(GroupUseNode))
return HttpResponse(json.dumps(GroupUseNode))
debug:
1.editGroup:53 Uncaught TypeError: parent.$ is not a function
解决:在父页面引入jquery
2.父页面传参数给子页面,明明有值,但是子页面取不到值
原因:这是因为js加载执行有时候在页面渲染之前,父页面给子页面传参前的时候js已经执行了
解决:(摘抄自:https://blog.csdn.net/qq_26483671/article/details/79464564)
方式一:
window.οnlοad=function(){}
方式二:
$(document).ready{ }
方式三:
$(function(){}
3.外键update报错
先delete再create可以
原因:未知
解决:待查明解决
原文:https://blog.51cto.com/linzb/2855871