SpringBoot+layui实现表格数据渲染和条件查询时Thymeleaf模板报错

ERROR 15028 — [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: “class path resource [templates/admin/user_list.html]”)] with root cause

报错原因

2023-09-15 15:47:12.799 ERROR 15028 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/admin/user_list.html]")] with root cause

org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "
                        {checkbox: true, fixed: true},
                        {field:'userId',title: 'ID', sort:true},
                        {field: 'userName',title: '用户名'},
                        {field: 'userPwd',title: '密码'},
                        {field: 'userEmail',title: '邮箱'},
                        {field: 'userRealName',title: '真实姓名'},
                        {field: 'userPhone',title: '手机号码'},
                        {field: 'userRegisterTime',title: '注册时间'},
                        {field: 'userUpdateTime',title: '更新时间'}
                    " (template: "admin/user_list" - line 142, col 28)
	at org.thymeleaf.standard.expression.StandardExpressionParser.parseExpression(StandardExpressionParser.java:131) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.standard.expression.StandardExpressionParser.parseExpression(StandardExpressionParser.java:62) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.standard.expression.StandardExpressionParser.parseExpression(StandardExpressionParser.java:44) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.engine.EngineEventUtils.parseAttributeExpression(EngineEventUtils.java:220) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.engine.EngineEventUtils.computeAttributeExpression(EngineEventUtils.java:207) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.standard.processor.AbstractStandardExpressionAttributeTagProcessor.doProcess(AbstractStandardExpressionAttributeTagProcessor.java:125) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1314) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleOpenElementEnd(TemplateHandlerAdapterMarkupHandler.java:304) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleOpenElementEnd(InlinedOutputExpressionMarkupHandler.java:278) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.performInlining(OutputExpressionInlinePreProcessorHandler.java:440) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleText(OutputExpressionInlinePreProcessorHandler.java:146) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleText(InlinedOutputExpressionMarkupHandler.java:80) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.attoparser.HtmlMarkupHandler.handleText(HtmlMarkupHandler.java:208) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.attoparser.AbstractChainedMarkupHandler.handleText(AbstractChainedMarkupHandler.java:203) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:557) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.attoparser.MarkupParser.parse(MarkupParser.java:257) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1372) ~[spring-webmvc-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118) ~[spring-webmvc-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057) ~[spring-webmvc-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123) ~[druid-1.1.10.jar:1.1.10]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:94) ~[spring-web-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.1.11.RELEASE.jar:5.1.11.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_371]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_371]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at java.lang.Thread.run(Thread.java:750) [na:1.8.0_371]

2023-09-15 15:47:12.812 ERROR 15028 --- [nio-8080-exec-1] s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/user/findAll] and exception [An error happened during template parsing (template: "class path resource [templates/admin/user_list.html]")] as the response has already been committed. As a result, the response may have the wrong status code.

我的user_list.html下Layui中的JS代码

<script type="text/javascript" >
            // 加载table和form模块
            layui.use(['table','form'],function () {
                let table = layui.table;
                let form = layui.form;
                
                //渲染表格
                table.render({
                    elem: '#listTable',
                    url:'/user/findAll',
                    cols:[[
                        {checkbox: true, fixed: true},
                        {field:'userId',title: 'ID', sort:true},
                        {field: 'userName',title: '用户名'},
                        {field: 'userPwd',title: '密码'},
                        {field: 'userEmail',title: '邮箱'},
                        {field: 'userRealName',title: '真实姓名'},
                        {field: 'userPhone',title: '手机号码'},
                        {field: 'userRegisterTime',title: '注册时间'},
                        {field: 'userUpdateTime',title: '更新时间'}
                    ]],
                    page: true, // 开启分页
                    limit: 10, // 每页显示的数量
                    limits: [10, 20, 30], // 每页可选择的数量
                    height: 'full-200', // 表格高度
                    checkbox: true, // 显示复选框
                    fixed: true // 固定表头和列
                });

                //监听搜索表单提交事件
                form.on('submit(searchBtn)',function (data) {
                    // var name = data.field.searchInputName;
                    // var email = data.field.searchInputEmail;
                    // var phone = data.field.searchInputPhone;
                    let searchByName = $('#searchInputName').val();
                    let searchByEmail = $('#searchInputEmail').val();
                    let searchByPhone = $('#searchInputPhone').val();

                    // 检查关键字是否为空
                    if (searchByName.trim() === '' && searchByEmail.trim() === '' && searchByPhone.trim() === ''){
                        layer.msg("请输入关键字");
                        return;
                    }

                    // 发送查询请求
                    table.reload('userTable',{
                        where:{
                            username:searchByName,
                            userEmail:searchByEmail,
                            userPhone:searchByPhone
                        }
                    });

                    return false;
                });
            });
            
        </script>

问题解决:在script标签中添加th:inline="none"

<script type="text/javascript" th:inline="none"></script>

问题二

  • 在实现添加用户操作时出现的错误
    在这里插入图片描述

检查了添加用户的弹出层中问题所在的一个小细节:括号中的name未加单引号

在这里插入图片描述
我的user_list.js所有代码

// 加载table和form模块
layui.use(['table','form','layer','jquery'],function () {
    let table = layui.table;
    let form = layui.form;
    let layer = layui.layer;
    let $ = layui.jquery;

    // 渲染表格
    table.render({
        elem: '#userTable',
        url: '/user/find',
        page:true,
        limit:10,
        limits: [10, 20, 30],
        cellMinWidth:60,
        cols:[[
            {type: 'checkbox', fixed: true}, // 单选框
            {field:'userId', title: 'ID', width:80, sort: true, fixed: true},
            {field:'username',title: '用户名'},
            {field:'userPwd',title: '密码'},
            {field:'userEmail',title: '邮箱'},
            {field:'userRealName',title: '真实姓名'},
            {field:'userPhone',title: '手机号'},
            {field:'userRegisterTime',title: '注册时间'},
            {field:'userUpdateTime',title: '修改时间'},
            {field: 'operation', title: '操作', toolbar:'#operation-bar',
                fixed: 'right',
                width: 134,
                minWidth: 125,
            }
        ]],
        toolbar: '#toolbar-header', //开启头部工具栏,并为其绑定左侧模板
        defaultToolbar: ['filter', 'exports', 'print']//头部工具栏右侧
    });


    // 添加用户
    table.on('toolbar(userTable)', function(obj){
        if(obj.event === 'add'){
            layer.open({
                type:2,
                title:'添加',
                content:['/user/add','yes'],
                area: ['680px', '520px'],
                btn: ['确认添加', '取消'],
                maxmin:true,
                btnAlign: 'c',
                yes:function (index, layero) {
                    // 获取iframe窗口
                    var iframeWin = window[layero.find('iframe')[0][name]];
                    // 获取表单中的数据
                    var username = iframeWin.$('#username').val();
                    var userPwd = iframeWin.$('#userPwd').val();
                    var userEmail = iframeWin.$('#userEmail').val();
                    var userRealName = iframeWin.$('#userRealName').val();
                    var userPhone = iframeWin.$('#userPhone').val();
                    // 发送请求
                    $.ajax({
                        url: '/user/add',
                        type: 'POST',
                        data: {
                            username: username,
                            userPwd: userPwd,
                            userEmail: userEmail,
                            userRealName: userRealName,
                            userPhone: userPhone
                        },
                        success: function(res){
                            if(res.code === 0){
                                layer.msg('添加成功');
                                table.reload('userTable');
                                layer.close(index);
                            }else{
                                layer.msg('添加失败');
                            }
                        },
                        error:function (data) {
                            console.log(data);
                        }
                    });
                }
            });
        }
    });

    // 监听表格行工具条事件
    table.on('tool(userTable)', function(obj){
        let data = obj.data; // 当前行数据
        let layEvent = obj.event; // 获取点击的事件名
        let userId = data.userId;
        let $ = layui.$;

        if(layEvent === 'edit') {
            // 编辑操作
            layer.open({
                type: 2,
                title: '编辑',
                content: ['/user/'+ userId + '/edit','yes'],
                area: ['680px', '520px'],
                btn: ['保存', '取消'],
                btnAlign: 'c',
                yes: function(index, layero){
                    // 获取 iframe 的窗口对象
                    let iframeWin = window[layero.find('iframe')[0]['name']];
                    // 获取表单中的数据
                    let username = iframeWin.$('#username').val();
                    let userPwd = iframeWin.$('#userPwd').val();
                    let userEmail = iframeWin.$('#userEmail').val();
                    let userRealName = iframeWin.$('#userRealName').val();
                    let userPhone = iframeWin.$('#userPhone').val();

                    //提交表单
                    $.ajax({
                        url: '/user/' + userId + '/update',
                        type: 'post',
                        data:{
                            'username':username,
                            'userPwd':userPwd,
                            'userEmail':userEmail,
                            'userRealName':userRealName,
                            'userPhone':userPhone
                        },
                        // data: $('#editForm').serialize(),
                        success: function(res){
                            layer.msg('保存成功');
                            // 更新成功后,刷新表格
                            table.reload('userTable');
                            layer.close(index);
                        },
                        error: function(error){
                            layer.msg('保存失败'+error);
                        }
                    });
                },
                btn2: function(index, layero){
                    // 取消操作
                    layer.close(index);
                }
            });

        } else if(layEvent === 'delete') {
            // 删除操作
            layer.confirm('确定删除此用户吗?',function (index) {
                $.ajax({
                    type: 'get',
                    url: '/user/' + userId+'/delete',
                    success: function(res){
                        layer.msg('删除成功');
                        table.reload('userTable');
                    },
                    error: function(){
                        layer.msg('删除失败');
                    }
                });
                layer.close(index);
            })
        }
    });

    //监听搜索表单提交事件
    form.on('submit(searchBtn)',function (data) {
        console.log(data);
        let userName = data.field.username;
        let userEmail = data.field.userEmail;
        let userPhone = data.field.userPhone;

        let searchByName = $('#searchInputName').val();
        let searchByEmail = $('#searchInputEmail').val();
        let searchByPhone = $('#searchInputPhone').val();

        // 检查关键字是否为空
        if (searchByName.trim() === '' && searchByEmail.trim() === '' && searchByPhone.trim() === ''){
            layer.msg("请输入关键字");
            return;
        }

        // 发送查询请求执行查询
        table.reload('userTable',{
            where:{
                username:userName || undefined,
                userEmail:userEmail || undefined,
                userPhone:userPhone || undefined,
                // 如果关键字为空则传递undefined给后端接口
            },
            page: {
                curr: 1 // 搜索后跳转至第1页
            }
        });
        return false;// 阻止表单默认提交
    });

});

问题解决:

//未修改前
let iframeWin = window[layero.find('iframe')[0][name]];
//修改后
let iframeWin = window[layero.find('iframe')[0]['name']];

Layui中的table.on()

table.on('tool(userTable)')table.on('toolbar(userTable)')的区别

  • table.on(‘tool(userTable)’):
    这个事件监听函数用于监听表格中的工具条点击事件。当表格中的工具条(通常是每一行数据后面的操作按钮)被点击时,会触发此事件。在该事件处理函数内部,可以根据不同的工具条类型进行相应的操作,例如编辑、删除等。
    示例代码:
table.on('tool(userTable)', function(obj){
  var data = obj.data; // 获取当前行的数据
  var layEvent = obj.event; // 获取触发的工具条类型

  if(layEvent === 'edit'){
    // 编辑操作
  } else if(layEvent === 'delete'){
    // 删除操作
  } else if(layEvent === 'detail'){
    // 查看详情操作
  }
  // ...
});
  • table.on(‘toolbar(userTable)’):
    这个事件监听函数用于监听表格的工具栏点击事件。通常,Layui的表格插件会在表格的顶部或底部添加一个工具栏,用于批量操作或其他自定义操作。当工具栏按钮被点击时,会触发此事件。
    示例代码:
table.on('toolbar(userTable)', function(obj){
  var layEvent = obj.event; // 获取触发的工具栏按钮类型

  if(layEvent === 'add'){
    // 添加操作
  } else if(layEvent === 'batchDelete'){
    // 批量删除操作
  } else if(layEvent === 'export'){
    // 导出操作
  }
  // ...
});

总结:
table.on(‘tool(userTable)’)用于监听行工具条的点击事件。
table.on(‘toolbar(userTable)’)用于监听表格工具栏的点击事件。
两者主要区别在于监听的事件类型不同,以及事件处理函数中对应的操作目标(行数据还是整个表格)。根据具体的需求,使用相应的事件监听函数来处理对应的事件。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一个非常流行的Java框架,可以轻松地创建Web应用程序。Layui是一个流行的前端UI框架,可以帮助我们快速地创建漂亮的Web页面。在这里,我将向你展示如何使用Spring Boot和Layui实现基本的增删改查功能。 首先,我们需要创建一个Spring Boot项目。你可以使用Spring Initializr来创建一个新项目,也可以使用Eclipse或IntelliJ IDEA等IDE来创建一个新项目。 接下来,我们需要添加一些依赖项。在这个例子中,我们将使用Spring Data JPA来访问数据库。在pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> ``` 我们还需要添加Spring Boot和Layui的依赖项。在pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>layui</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.1.0</version> </dependency> ``` 接下来,我们需要配置数据库连接。在application.properties文件中添加以下代码: ``` spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.h2.console.enabled=true ``` 在这里,我们使用H2内存数据库来简化示例。在实际应用程序中,你可能需要使用其他数据库,例如MySQL或PostgreSQL。 现在,我们将创建一个实体类来表示我们的数据表。在这个例子中,我们将创建一个简单的数据表,其中包含id,name和age字段。创建一个名为Person的类,并在其中添加以下代码: ```java @Entity @Table(name = "person") public class Person { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private int age; // getters and setters } ``` 接下来,我们将创建一个Spring Data JPA存储库来访问数据库。创建一个名为PersonRepository的接口,并在其中添加以下代码: ```java @Repository public interface PersonRepository extends JpaRepository<Person, Long> { } ``` 现在我们已经设置好了数据访问层,我们将创建一个控制器来处理HTTP请求。创建一个名为PersonController的类,并在其中添加以下代码: ```java @Controller public class PersonController { @Autowired private PersonRepository personRepository; @GetMapping("/") public String index(Model model) { List<Person> persons = personRepository.findAll(); model.addAttribute("persons", persons); return "index"; } @GetMapping("/add") public String addForm(Model model) { return "add"; } @PostMapping("/add") public String addSubmit(@ModelAttribute Person person) { personRepository.save(person); return "redirect:/"; } @GetMapping("/edit/{id}") public String editForm(@PathVariable Long id, Model model) { Person person = personRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Invalid person id:" + id)); model.addAttribute("person", person); return "edit"; } @PostMapping("/edit/{id}") public String editSubmit(@PathVariable Long id, @ModelAttribute Person person, BindingResult bindingResult) { if (bindingResult.hasErrors()) { person.setId(id); return "edit"; } personRepository.save(person); return "redirect:/"; } @GetMapping("/delete/{id}") public String delete(@PathVariable Long id) { personRepository.deleteById(id); return "redirect:/"; } } ``` 在这里,我们定义了五个方法来处理HTTP请求: - `index()` - 处理根路径请求,列出所有人员记录。 - `addForm()` - 处理添加人员记录请求,返回一个包含表单的页面。 - `addSubmit()` - 处理添加人员记录请求,将表单提交的数据保存到数据库中。 - `editForm()` - 处理编辑人员记录请求,返回一个包含表单的页面。 - `editSubmit()` - 处理编辑人员记录请求,将表单提交的数据更新到数据库中。 - `delete()` - 处理删除人员记录请求,从数据库中删除指定的记录。 现在我们需要创建HTML模板来呈现数据。创建一个名为index.html的文件,并在其中添加以下代码: ```html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Person List</title> <link rel="stylesheet" type="text/css" href="/webjars/layui/2.5.4/css/layui.css"> <script type="text/javascript" src="/webjars/jquery/3.1.0/jquery.min.js"></script> <script type="text/javascript" src="/webjars/layui/2.5.4/layui.js"></script> </head> <body> <div class="layui-container"> <div class="layui-row"> <div class="layui-col-md12"> <h2>Person List</h2> </div> </div> <div class="layui-row"> <div class="layui-col-md12"> <table class="layui-table"> <thead> <tr> <th>ID</th> <th>Name</th> <th>Age</th> <th>Actions</th> </tr> </thead> <tbody> <tr th:each="person : ${persons}"> <td th:text="${person.id}"></td> <td th:text="${person.name}"></td> <td th:text="${person.age}"></td> <td> <button class="layui-btn layui-btn-xs" onclick="location.href='/edit/'+${person.id}">Edit</button> <button class="layui-btn layui-btn-danger layui-btn-xs" onclick="location.href='/delete/'+${person.id}">Delete</button> </td> </tr> </tbody> </table> </div> </div> <div class="layui-row"> <div class="layui-col-md12"> <button class="layui-btn" onclick="location.href='/add'">Add Person</button> </div> </div> </div> </body> </html> ``` 这个模板使用Thymeleaf作为模板引擎,并使用Layui来创建漂亮的表格和按钮。它列出了所有人员记录,并提供了添加,编辑和删除记录的链接。 接下来,我们需要创建一个名为add.html的文件,其中包含添加人员记录的表单。添加以下代码: ```html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Add Person</title> <link rel="stylesheet" type="text/css" href="/webjars/layui/2.5.4/css/layui.css"> <script type="text/javascript" src="/webjars/jquery/3.1.0/jquery.min.js"></script> <script type="text/javascript" src="/webjars/layui/2.5.4/layui.js"></script> </head> <body> <div class="layui-container"> <div class="layui-row"> <div class="layui-col-md12"> <h2>Add Person</h2> </div> </div> <div class="layui-row"> <div class="layui-col-md12"> <form class="layui-form" method="post" action="/add"> <div class="layui-form-item"> <label class="layui-form-label">Name:</label> <div class="layui-input-block"> <input type="text" name="name" required lay-verify="required" placeholder="Enter name" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">Age:</label> <div class="layui-input-block"> <input type="text" name="age" required lay-verify="required" placeholder="Enter age" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <div class="layui-input-block"> <button class="layui-btn" lay-submit lay-filter="formDemo">Submit</button> <button type="reset" class="layui-btn layui-btn-primary">Reset</button> </div> </div> </form> </div> </div> </div> </body> </html> ``` 这个模板使用Layui创建一个包含name和age字段的表单。当用户提交表单,它将数据发送到服务器上的/add路由。 接下来,我们需要创建一个名为edit.html的文件,其中包含编辑人员记录的表单。添加以下代码: ```html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Edit Person</title> <link rel="stylesheet" type="text/css" href="/webjars/layui/2.5.4/css/layui.css"> <script type="text/javascript" src="/webjars/jquery/3.1.0/jquery.min.js"></script> <script type="text/javascript" src="/webjars/layui/2.5.4/layui.js"></script> </head> <body> <div class="layui-container"> <div class="layui-row"> <div class="layui-col-md12"> <h2>Edit Person</h2> </div> </div> <div class="layui-row"> <div class="layui-col-md12"> <form class="layui-form" method="post" th:action="@{'/edit/'+${person.id}}" th:object="${person}"> <div class="layui-form-item"> <label class="layui-form-label">Name:</label> <div class="layui-input-block"> <input type="text" name="name" required lay-verify="required" th:value="${person.name}" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">Age:</label> <div class="layui-input-block"> <input type="text" name="age" required lay-verify="required" th:value="${person.age}" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <div class="layui-input-block"> <button class="layui-btn" lay-submit lay-filter="formDemo">Submit</button> <button type="reset" class="layui-btn layui-btn-primary">Reset</button> </div> </div> </form> </div> </div> </div> </body> </html> ``` 这个模板使用Layui创建一个包含name和age字段的表单,并将表单数据预填充为当前记录的值。当用户提交表单,它将数据发送到服务器上的/edit/{id}路由。 最后,我们需要为我们的应用程序创建一个入口点。创建一个名为Application的类,并在其中添加以下代码: ```java @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 现在我们已经设置好了我们的应用程序,运行它并访问http://localhost:8080/,你应该能够看到一个包含所有人员记录的表格,以及添加,编辑和删除记录的链接。 这就是使用Spring Boot和Layui实现网页上增删改查的基本步骤。当然,你可以扩展它以满足你的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值