您现在的位置是:首页 > 文章详情

curd组件2:按钮实现

日期:2021-06-30点击:645

参考:https://blog.csdn.net/dixian4894/article/details/102209151

上篇没有区分哪些字段可以编辑,而且如果像性别这种,在编辑的时候应该是个选择器,所以,在fields_config添加attr属性,并在attr赋值是否可编辑,编辑状态所用html标签,select的数据来源属性,一个例子如下:

 { "field_name": "性别", "field_in_db": "gender", "display": True, "show_data": "!GENDER", "attr": { "editable": True, "htmlLabel": "select", "selectDataFrom":"GENDER" } },

前端得到这些数据,便可实现,编辑,全选,反选,取消按钮,代码如下:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> <style> .data-display{ margin: 200px; } </style> </head> <body> <div class="data-display"> <div class="btn-group" role="group" aria-label="..."> <button id="SelectAll" type="button" class="btn btn-default">全选</button> <button id="Reserve" type="button" class="btn btn-default">反选</button> <button id="Cancel" type="button" class="btn btn-default">取消</button> <button id="EditMode" type="button" class="btn btn-default">进入编辑模式</button> <button id="Del" class="btn btn-default">批量删除</button> <button id='save' type="button" class="btn btn-default">保存</button> </div> <table class="table table-bordered" id="Datatable"> <thead id="table_th"></thead> <tbody id="table_td"></tbody> </table> </div> </body> <script src="/static/js/jquery-3.5.1.min.js"> </script> <script> $(function () { initTable(); BindEditMode(); BindCheckboxEditMode(); BindSelectAll(); BindCancel(); BindReserve(); }) function initTable(){ $.ajax({ url:"getCurdData", type:'POST', dataType:'Json', success:function (arg) { initchoice(arg.choices_dict) initThead(arg.fields_config) initTbody(arg.data,arg.fields_config) } }) } function initThead(field) { tr_ele=$("<tr></tr>") $.each(field,function (k,v) { if(v["display"]){ th_ele=$("<th></th>") th_ele.text(v["field_name"]) tr_ele.append(th_ele) } $("#table_th").append(tr_ele) }) } function initTbody(data,field) { // 数据展示一般做法是,取出展示的字段,然后循环数据列表判断是否在里面,有则展示 // 但是这么做有个缺点是数据和字段的顺序要对应(因为是以数据为顺序,而字段顺序是可能变化的),而且不利于扩展 // 这里采用先循环数据列表,再循环field字段列表,根据字段的列表的顺序反选查找赋值 // 缺点是多次循环field比较耗性能,但是扩展能力变强了 $.each(data,function (data_k,data_v) { tr_ele=$("<tr></tr>") $.each(field,function (field_k,field_v) { if(field_v.display){ td_ele=$("<td></td>") //赋值attr $.each(field_v.attr,function (attr_k,attr_v) { td_ele.attr(attr_k,attr_v) }) if(field_v["show_data"][0]==='@'){ td_ele.html(data_v[field_v["field_in_db"]]) } else if(field_v["show_data"][0]==='!'){ var f_v=field_v["show_data"] var choice_list=f_v.substring(1,f_v.length) var choice_v=value_from_choice_list(data_v[field_v["field_in_db"]],window[choice_list]) td_ele.html(choice_v) } else{ td_ele.html(field_v["show_data"]) } tr_ele.append(td_ele) } }) $("#table_td").append(tr_ele) }) } function initchoice(choice_dict) { $.each(choice_dict,function (i,j) { // a='123'相当于window[a]='123' // 这里把choices列表转化为全局变量 window[i]=j; }) } function value_from_choice_list(index,choice) { //choice格式:{0: (2) ["male", "男"],} //v[0]="male",v[1]="男" ret=null $.each(choice,function (k,v) { if(v[0] === index){ ret=v[1] //js 的return只能跳出当前循环,类似shell的break // 所以额外赋值 return } }) return ret } function BindEditMode() { $('#EditMode').click(function () { //进入编辑模式,应该有个标记,才能区分进入与退出,这里用btn-info属性给button上色 //所以也用这个属性判断是否在编辑模式,有则是应退出,无则不是应进入 //也可以自己定义一个属性判断 if($(this).hasClass("btn-info")) { OutEditMode() }else{ IntoEditMode() } }) } function IntoEditMode() { $('#EditMode').addClass("btn-info") $('#EditMode').text("退出编辑模式") //查找checkbox是否选中,有则查找对应tr进入编辑 $("#table_td").find(":checked").each(function () { $cur_tr=$(this).parent().parent() TrIntoEdit($cur_tr) }) } function OutEditMode() { $('#EditMode').removeClass("btn-info") $('#EditMode').text("进入编辑模式") $("#table_td").find(":checked").each(function () { $cur_tr=$(this).parent().parent() TrOutEdit($cur_tr) }) } function TrIntoEdit(cur_tr) { //给当前行加个颜色表示正在编辑 cur_tr.addClass("info") // 查找tr下的td含有editable属性的元素进行渲染 cur_tr.find('[editable="true"]').each(function () { var htmllabel = $(this).attr('htmllabel') if(htmllabel === 'select'){ //如果类型是select,获取列表值,渲染成select选择 var selectData=$(this).attr('selectDataFrom') var select_ele=$("<select></select>") var cur_select_v=$(this).html() $.each(window[selectData],function (select_k,select_v) { var option_ele=$("<option></option>") option_ele.val(select_v[0]) option_ele.html(select_v[1]) if(cur_select_v === select_v[1]){ option_ele.attr("selected",true) } select_ele.append(option_ele) }) $(this).html(select_ele) }else { label_v=$(this).text() input_ele=$("<input>") input_ele.val(label_v) $(this).html(input_ele) } }) } function TrOutEdit(cur_tr) { //当前行去掉颜色表示退出 cur_tr.removeClass("info") // 查找tr下的td含有editable属性的元素进行渲染 cur_tr.find('[editable="true"]').each(function () { var htmllabel = $(this).attr('htmllabel') if(htmllabel === 'select'){ //如果类型是select,获取选中的值,赋值 var select_ele = $(this).children().first() var cur_select_v=select_ele[0].selectedOptions[0].innerHTML $(this).html(cur_select_v) }else { var input_ele = $(this).children().first() var cur_input_v=input_ele.val() $(this).html(cur_input_v) } }) } function BindCheckboxEditMode() { // IntoEditMode的函数有个bug,如果先进入编辑模式,再点击checkbox按钮 // 当前行不会进入编辑模式,这是因为点击button比勾选快 // 所以需要对CheckBox进行编辑模式下的事件委托 $("#table_td").on('click',':checkbox',function () { if ($("#EditMode").hasClass("btn-info")) { cur_status = $(this).prop('checked'); var $cur_tr = $(this).parent().parent(); if(cur_status){ TrIntoEdit($cur_tr) }else{ TrOutEdit($cur_tr) } } }) } function BindSelectAll() { // 全选分两种,编辑模式下,要TrIntoEdit,普通则勾选即可 $('#SelectAll').click(function () { // 全选只需处理未被选中的即可 $("#table_td").find(":checkbox").not(":checked").each(function () { if($("#EditMode").hasClass("btn-info")){ $(this).prop('checked',true); var $cur_tr = $(this).parent().parent(); TrIntoEdit($cur_tr) }else{ $(this).prop('checked',true); } }) }) } function BindReserve() { // 反选需要两种情况,编辑模式下,如果选中则TrOutEdit,未选中则TrIntoEdit // 普通则反选即可 $('#Reserve').click(function () { $("#table_td").find(":checkbox").each(function () { if($("#EditMode").hasClass("btn-info")){ var $cur_tr = $(this).parent().parent(); if($(this).prop('checked')){ $(this).prop('checked',false); TrOutEdit($cur_tr) }else{ $(this).prop('checked',true); TrIntoEdit($cur_tr) } }else{ if($(this).prop('checked')){ $(this).prop('checked',false); } else{ $(this).prop('checked',true); } } }) }) } function BindCancel() { // 取消跟全选相反,只需要处理选中的checkbox // 也是两种情况,若编辑模式,则TrOutEdit,否则去掉勾选即可 $('#Cancel').click(function () { $("#table_td").find(":checked").each(function () { if($("#EditMode").hasClass("btn-info")){ $(this).prop('checked',false); var $cur_tr = $(this).parent().parent(); TrOutEdit($cur_tr) }else{ $(this).prop('checked',false); } }) }) } </script> </html>

在实现删除和保存的时候,需要改动的东西比较多,因为保存意味着更新,所以要知道旧值和新值,如果新旧不一样才更新,这意味着多加字段标记旧属性,修改赋值代码等,具体如下:在实现删除和保存的时候,需要改动的东西比较多,因为保存意味着更新,所以要知道旧值和新值,如果新旧不一样才更新,这意味着多加字段标记旧属性,修改赋值代码等,具体如下:

config属性赋值更新: 之前: "attr": { "editable":True, "htmlLabel":"" } 之后: "attr": { "editable":True, "origin_v":"@field_name", "htmlLabel":"" } initTbody函数修改: tr赋值属性记录当前行id; 之前: tr_ele=$("<tr></tr>") 之后: tr_ele=$("<tr></tr>") var old_data_id=data_v["id"] tr_ele.attr("old_data_id",old_data_id) td属性赋值更新: //赋值attr // 赋值field_in_db属性,用以在更新时找到对应数据库字段 td_ele.attr("field_in_db",field_v["field_in_db"]) $.each(field_v.attr,function (attr_k,attr_v) { // "origin_v":"@field_name",属性赋值需转为数据库的值 if(attr_k==="origin_v") { attr_v=data_v[field_v["field_in_db"]] td_ele.attr(attr_k,attr_v) }else{ td_ele.attr(attr_k,attr_v) } }) TrIntoEdit函数修改: 之前: cur_tr.addClass("info") 之后: cur_tr.addClass("info") // 标记当前行已编辑,表明可能数据变更,没有则没变更 cur_tr.attr("has-edit",true) TrOutEdit退出赋新值: 之前: var select_ele = $(this).children().first() var cur_select_v=select_ele[0].selectedOptions[0].innerHTML $(this).html(cur_select_v) 之后: var select_ele = $(this).children().first() var cur_select_v=select_ele[0].selectedOptions[0].innerHTML $(this).html(cur_select_v) // 赋新值属性 origin_v=$(this).prop("origin_v") change_v=DBvalue_from_choice_list(cur_select_v,window[selectdata]) if(origin_v != change_v){ $(this).attr("change_v",change_v) } 添加save 按钮: function BindSave() { // 收集改变的行,每行为一条记录,从tr标签读取旧数据id // 从td读取field_name作为key,读取chang_v为value,若无则不赋值 $('#Save').click(function () { // 如果编辑模式下,相当于点了取消 $('#Cancel').click() // 用update_list作为标记,告知后端传送的是更新的数据 var update_list=[] $('#table_td').find('tr[has-edit="true"]').each(function () { record={} id_v=$(this).attr("old_data_id") record["id"]=id_v $(this).children('[editable="true"]').each(function(){ if($(this).attr("change_v")) { field_k = $(this).attr("field_in_db") field_v = $(this).attr("change_v") record[field_k] = field_v } }) update_list.push(record); }) $.ajax({ url: "getCurdData", type: 'POST', data: {'update_list': JSON.stringify(update_list)}, dataType: 'json', success:function (arg) { if(arg.status=='ok'){ initTbody() } } }) }) } 添加删除按钮: function BindDel() { // 删除按钮要获取当前选中行的数据库id,还要弹窗提示确认 $('#Del').click(function () { del_list=[] $('#table_td').find(":checked").each(function () { record={} // save找的是tr,这里是td,所以需parent id_v=$(this).parent().parent().attr("old_data_id") console.log($(this)) record["id"]=id_v }) del_list.push(record) var r=confirm("确定删除?"); if(r){ $.ajax({ url: "getCurdData", type: 'POST', data: {'del_list': JSON.stringify(del_list)}, dataType: 'json', success:function (arg) { if(arg.status=='ok'){ initTbody() } } }) } }) }

按钮都实现后,就可以提取共同的部分封装成js(增加功能:requestURL,用pager分页等),最终代码如下:

后端view(无实现保存和删除)

def getCurdData(request): print(request.POST) Gender_list=list(User.GENDER) work_list=[('1', '开'), ('2', '关')] fields_config=[ { "field_name": "选项", "field_in_db": "", "display": True, "show_data": "<input type='checkbox' />", "attr":{ } }, { "field_name":"用户名", "field_in_db":"username", "display":True, "show_data":"@field_name", "attr": { "editable":True, "origin_v":"@field_name", "htmlLabel":"", } }, { "field_name": "密码", "field_in_db": "password", "display": True, "show_data": "@field_name" }, { "field_name": "邮件", "field_in_db": "email", "display": True, "show_data": "@field_name", "attr": { "editable": True, "htmlLabel": "", "origin_v":"@field_name", } }, { "field_name": "性别", "field_in_db": "gender", "display": True, "show_data": "!GENDER", "attr": { "editable": True, "origin_v": "@field_name", "htmlLabel": "select", "selectDataFrom":"GENDER" } }, { "field_name": "电话", "field_in_db": "tel", "display": True, "show_data": "@field_name" }, { "field_name": "生日", "field_in_db": "birthday", "display": True, "show_data": "@field_name" }, { "field_name": "别名", "field_in_db": "name", "display": True, "show_data": "@field_name" }, ] data_list=list(User.objects.all().values()) result={ "fields_config":fields_config, "data":data_list, "choices_dict":{ "GENDER":Gender_list, "work":work_list, } } return HttpResponse(json.dumps(result,cls=CJsonEncoder))

删除和保存的POST数据如下:

<QueryDict: {'del_list': ['[{"id":"1"}]']}> [30/Jun/2021 16:35:21] "POST /getCurdData HTTP/1.1" 200 1574 <QueryDict: {'update_list': ['[{"id":"1"},{"id":"2"}]']}>

CURDbyLinzb.js

 $(function () { function initTable(pager){ // pager:提取第pager页的数据 $.ajax({ url:requestURL, type:'GET', data:{'pager':pager}, dataType:'Json', success:function (arg) { initchoice(arg.choices_dict) initThead(arg.fields_config) initTbody(arg.data,arg.fields_config) } }) } function initThead(field) { tr_ele=$("<tr></tr>") $.each(field,function (k,v) { if(v["display"]){ th_ele=$("<th></th>") th_ele.text(v["field_name"]) tr_ele.append(th_ele) } $("#table_th").append(tr_ele) }) } function initTbody(data,field) { // save按钮重载时,会重新生成,所以需清空 $('#table_td').empty(); // 数据展示一般做法是,取出展示的字段,然后循环数据列表判断是否在里面,有则展示 // 但是这么做有个缺点是数据和字段的顺序要对应(因为是以数据为顺序,而字段顺序是可能变化的),而且不利于扩展 // 这里采用先循环数据列表,再循环field字段列表,根据字段的列表的顺序反选查找赋值 // 缺点是多次循环field比较耗性能,但是扩展能力变强了 $.each(data,function (data_k,data_v) { tr_ele=$("<tr></tr>") // tr赋值属性,标记当前行在数据库中的id,为更新做旧数据标记 var old_data_id=data_v["id"] tr_ele.attr("old_data_id",old_data_id) $.each(field,function (field_k,field_v) { if(field_v.display){ td_ele=$("<td></td>") // td 赋值attr // 赋值field_in_db属性,用以在更新时找到对应数据库字段 td_ele.attr("field_in_db",field_v["field_in_db"]) $.each(field_v.attr,function (attr_k,attr_v) { // "origin_v":"@field_name",属性赋值需转为数据库的值 if(attr_k==="origin_v") { attr_v=data_v[field_v["field_in_db"]] td_ele.attr(attr_k,attr_v) }else{ td_ele.attr(attr_k,attr_v) } }) if(field_v["show_data"][0]==='@'){ td_ele.html(data_v[field_v["field_in_db"]]) } else if(field_v["show_data"][0]==='!'){ var f_v=field_v["show_data"] var choice_list=f_v.substring(1,f_v.length) var choice_v=value_from_choice_list(data_v[field_v["field_in_db"]],window[choice_list]) td_ele.html(choice_v) } else{ td_ele.html(field_v["show_data"]) } tr_ele.append(td_ele) } }) $("#table_td").append(tr_ele) }) } function initchoice(choice_dict) { $.each(choice_dict,function (i,j) { // a='123'相当于window[a]='123' // 这里把choices列表转化为全局变量 window[i]=j; }) } function value_from_choice_list(index,choice) { //choice格式:{0: (2) ["male", "男"],} //v[0]="male",v[1]="男" ret=null $.each(choice,function (k,v) { if(v[0] === index){ ret=v[1] //js 的return只能跳出当前循环,类似shell的break // 所以额外赋值 return } }) return ret } function DBvalue_from_choice_list(index,choice) { //choice格式:{0: (2) ["male", "男"],} //v[0]="male",v[1]="男" ret=null $.each(choice,function (k,v) { if(v[1] === index){ ret=v[0] //js 的return只能跳出当前循环,类似shell的break // 所以额外赋值 return } }) return ret } function BindEditMode() { $('#EditMode').click(function () { //进入编辑模式,应该有个标记,才能区分进入与退出,这里用btn-info属性给button上色 //所以也用这个属性判断是否在编辑模式,有则是应退出,无则不是应进入 //也可以自己定义一个属性判断 if($(this).hasClass("btn-info")) { OutEditMode() }else{ IntoEditMode() } }) } function IntoEditMode() { $('#EditMode').addClass("btn-info") $('#EditMode').text("退出编辑模式") //查找checkbox是否选中,有则查找对应tr进入编辑 $("#table_td").find(":checked").each(function () { $cur_tr=$(this).parent().parent() TrIntoEdit($cur_tr) }) } function OutEditMode() { $('#EditMode').removeClass("btn-info") $('#EditMode').text("进入编辑模式") $("#table_td").find(":checked").each(function () { $cur_tr=$(this).parent().parent() TrOutEdit($cur_tr) }) } function TrIntoEdit(cur_tr) { //给当前行加个颜色表示正在编辑 cur_tr.addClass("info") // 标记当前行已编辑,表明可能数据变更,没有则没变更 cur_tr.attr("has-edit",true) // 查找tr下的td含有editable属性的元素进行渲染 cur_tr.find('[editable="true"]').each(function () { var htmllabel = $(this).attr('htmllabel') if(htmllabel === 'select'){ //如果类型是select,获取列表值,渲染成select选择 var selectData=$(this).attr('selectDataFrom') var select_ele=$("<select></select>") var cur_select_v=$(this).html() $.each(window[selectData],function (select_k,select_v) { var option_ele=$("<option></option>") option_ele.val(select_v[0]) option_ele.html(select_v[1]) if(cur_select_v === select_v[1]){ option_ele.attr("selected",true) } select_ele.append(option_ele) }) $(this).html(select_ele) }else { label_v=$(this).text() input_ele=$("<input>") input_ele.val(label_v) $(this).html(input_ele) } }) } function TrOutEdit(cur_tr) { //当前行去掉颜色表示退出 cur_tr.removeClass("info") // 查找tr下的td含有editable属性的元素进行渲染 cur_tr.find('[editable="true"]').each(function () { var htmllabel = $(this).attr('htmllabel') var selectdata = $(this).attr('selectDataFrom') if(htmllabel === 'select'){ //如果类型是select,获取选中的值,赋值 var select_ele = $(this).children().first() var cur_select_v=select_ele[0].selectedOptions[0].innerHTML $(this).html(cur_select_v) // 赋新值属性 origin_v=$(this).attr("origin_v") change_v=DBvalue_from_choice_list(cur_select_v,window[selectdata]) if(origin_v != change_v){ $(this).attr("change_v",change_v) } }else { var input_ele = $(this).children().first() var cur_input_v=input_ele.val() $(this).html(cur_input_v) origin_v=$(this).attr("origin_v") change_v=cur_input_v if(origin_v != change_v){ $(this).attr("change_v",change_v) } } }) } function BindCheckboxEditMode() { // IntoEditMode的函数有个bug,如果先进入编辑模式,再点击checkbox按钮 // 当前行不会进入编辑模式,这是因为点击button比勾选快 // 所以需要对CheckBox进行编辑模式下的事件委托 $("#table_td").on('click',':checkbox',function () { if ($("#EditMode").hasClass("btn-info")) { cur_status = $(this).prop('checked'); var $cur_tr = $(this).parent().parent(); if(cur_status){ TrIntoEdit($cur_tr) }else{ TrOutEdit($cur_tr) } } }) } function BindSelectAll() { // 全选分两种,编辑模式下,要TrIntoEdit,普通则勾选即可 $('#SelectAll').click(function () { // 全选只需处理未被选中的即可 $("#table_td").find(":checkbox").not(":checked").each(function () { if($("#EditMode").hasClass("btn-info")){ $(this).prop('checked',true); var $cur_tr = $(this).parent().parent(); TrIntoEdit($cur_tr) }else{ $(this).prop('checked',true); } }) }) } function BindReserve() { // 反选需要两种情况,编辑模式下,如果选中则TrOutEdit,未选中则TrIntoEdit // 普通则反选即可 $('#Reserve').click(function () { $("#table_td").find(":checkbox").each(function () { if($("#EditMode").hasClass("btn-info")){ var $cur_tr = $(this).parent().parent(); if($(this).prop('checked')){ $(this).prop('checked',false); TrOutEdit($cur_tr) }else{ $(this).prop('checked',true); TrIntoEdit($cur_tr) } }else{ if($(this).prop('checked')){ $(this).prop('checked',false); } else{ $(this).prop('checked',true); } } }) }) } function BindCancel() { // 取消跟全选相反,只需要处理选中的checkbox // 也是两种情况,若编辑模式,则TrOutEdit,否则去掉勾选即可 $('#Cancel').click(function () { $("#table_td").find(":checked").each(function () { if($("#EditMode").hasClass("btn-info")){ $(this).prop('checked',false); var $cur_tr = $(this).parent().parent(); TrOutEdit($cur_tr) }else{ $(this).prop('checked',false); } }) }) } function BindSave() { // 收集改变的行,每行为一条记录,从tr标签读取旧数据id // 从td读取field_name作为key,读取chang_v为value,若无则不赋值 $('#Save').click(function () { // 如果编辑模式下,相当于点了取消 $('#Cancel').click() // 用update_list作为标记,告知后端传送的是更新的数据 var update_list=[] $('#table_td').find('tr[has-edit="true"]').each(function () { record={} id_v=$(this).attr("old_data_id") record["id"]=id_v $(this).children('[editable="true"]').each(function(){ if($(this).attr("change_v")) { field_k = $(this).attr("field_in_db") field_v = $(this).attr("change_v") record[field_k] = field_v } }) update_list.push(record); }) $.ajax({ url: requestURL, type: 'POST', data: {'update_list': JSON.stringify(update_list)}, dataType: 'json', success:function (arg) { if(arg.status=='ok'){ initTbody(1) } } }) }) } function BindDel() { // 删除按钮要获取当前选中行的数据库id,还要弹窗提示确认 $('#Del').click(function () { del_list=[] $('#table_td').find(":checked").each(function () { record={} // save找的是tr,这里是td,所以需parent id_v=$(this).parent().parent().attr("old_data_id") if(id_v!=undefined) { record["id"] = id_v del_list.push(record) } }) var r=confirm("确定删除?"); if(r){ $.ajax({ url: requestURL, type: 'POST', data: {'del_list': JSON.stringify(del_list)}, dataType: 'json', success:function (arg) { if(arg.status=='ok'){ initTbody(1) } } }) } }) } jQuery.extend({ 'CreateCURD':function (url) { requestURL = url; initTable(1); BindEditMode(); BindCheckboxEditMode(); BindSelectAll(); BindCancel(); BindReserve(); BindSave(); BindDel(); }, 'TurnToPager':function (num) { inittable(num); } }) })

前端代码:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> <style> .data-display{ margin: 200px; } </style> </head> <body> <div class="data-display"> <div class="btn-group" role="group" aria-label="..."> <button id="SelectAll" type="button" class="btn btn-default">全选</button> <button id="Reserve" type="button" class="btn btn-default">反选</button> <button id="Cancel" type="button" class="btn btn-default">取消</button> <button id="EditMode" type="button" class="btn btn-default">进入编辑模式</button> <button id="Del" class="btn btn-default">批量删除</button> <button id='Save' type="button" class="btn btn-default">保存</button> </div> <table class="table table-bordered" id="Datatable"> <thead id="table_th"></thead> <tbody id="table_td"></tbody> </table> </div> </body> <script src="/static/js/jquery-3.5.1.min.js"> </script> <script src="/static/js/CURDbyLinzb.js"> </script> <script> $(function () { $.CreateCURD( 'getCurdData') }) </script> </html>
原文链接:https://blog.51cto.com/linzb/2960126
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章