返回

JqGrid更新后数据不刷新?详解原因及解决方案

php

JqGrid 更新后数据不刷新的问题及解决方案

接手了一个 PHP 发票应用,发现发票详情页的 JqGrid 在更新数据后,表格内容不会自动刷新,必须手动刷新整个页面才能看到更新后的数据。 增加和删除功能倒是没问题,就是这个编辑功能有点小毛病。 捣鼓了半天, JavaScript 和 JQuery 水平有限,一直没搞定。下面细说一下这个问题和解决办法。

一、 问题原因分析

根据代码和现象来看,问题出在 edit 操作上。 虽然数据库更新成功了,但 JqGrid 没有重新加载数据。 核心原因在于,虽然在successfunc 里有尝试刷新页面: window.location.reload(false); , 但这相当于重新加载了整个网页,而不是单单刷新 JqGrid 的数据。 在 inline editing 的情景下,期望的是无刷新更新 JqGrid 数据。 并且发现,代码中 reloadAfterSubmitafterSubmit 并未完全发挥作用。

二、 解决方案

既然知道问题是 JqGrid 没有正确地重新加载数据, 解决方法就是强制让它在编辑操作成功后重新加载数据。 有几个办法可以做到。

1. 使用 trigger("reloadGrid") (推荐)

这是最直接有效的方法。在数据更新成功的回调函数中,直接触发 JqGrid 的 reloadGrid 事件,强制 JqGrid 重新向服务器请求数据。

  • 原理: trigger("reloadGrid") 会告诉 jqGrid 重新加载数据。 如果 datatype 设置为 'json',jqGrid 会再次发送请求到 url 指定的地址,获取最新的数据并渲染表格。

  • 代码示例:

    修改 editOptions 对象:

    var editOptions = {
      keys: true,
      mtype: "POST",
      successfunc: function (response) {
        //原来使用了不太恰当的方式去尝试更新grid, 先注释掉:
        // var $self = $(list);
        // setTimeout(function () {
        //   window.location.reload(false);
        // }, 50);
    
        //判断如果PHP成功执行返回的是true
        if (response.responseText == 'true') {
          //触发刷新动作
            $("#list").trigger("reloadGrid");
            return true;
        }
    
        return false; //返回false给jqGrid说明有问题,它会保持编辑状态
      }
    };
    

    在 PHP 代码的 edit 部分,确保 editdetails 执行成功后,$success 的值为 "true" 的字符串:

      //changes don't refresh grid
      elseif($oper == "edit") {
          $Quantity = $_POST['Quantity'];
          $ProductID = $_POST['ProductID'];
          $UnitPrice = $_POST['UnitPrice'];
          $ExtendedPrice = $UnitPrice*$Quantity;
          $qeditdetails = "UPDATE tblorderdetails SET quantity = ?, price = ?, extended_price = ? WHERE product_id = ? AND order_id = ?";
        $editdetails = $pdo->prepare($qeditdetails);
          $editdetails->execute([$Quantity,$UnitPrice,$ExtendedPrice,$ProductID,$OrderID]);
        if ($editdetails) { $success = "true"; } //保持这个是string
        else{ $success = "false"; } //明确的加上如果数据库操作不成功的返回, 协助调试(这行可以按需选择加不加).
      }
    
  • 说明: 这里添加了对服务器返回值的判断 (response.responseText == 'true'),确保只有在服务器端处理成功后才刷新表格。 避免了由于服务器端错误或其他原因导致的不必要刷新。 同时让jqGrid理解服务器的操作是否成功。

2. 使用 setGridParamtrigger("reloadGrid") 结合 (适用于更复杂场景)

这种方法允许在重新加载数据之前,动态修改 JqGrid 的参数,例如改变请求的 URL、参数等。

  • 原理: 先通过 setGridParam 修改 JqGrid 的配置参数(比如 urlpostData),然后再调用 trigger("reloadGrid") 触发数据重新加载。

  • 代码示例:

    var editOptions = {
      keys: true,
      mtype: "POST",
      successfunc: function () {
        // 修改参数(如果需要),这里假设要加一个参数 newParam
        $("#list").jqGrid('setGridParam', {
          url: 'orderdetails_json.php', // 或者新的 URL, 根据你的场景来
          datatype: 'json', // 明确类型.
          postData: {newParam: 'newValue'},
          page: 1 // 重置到第一页,按需选择加不加
           }).trigger("reloadGrid");
    
        return [true]; //返回给jqGrid让它完成后续流程
      }
    };
    
  • 说明: 此处假设更改 urlpostData, 需要根据自己的需求, 选择适合的修改即可。 也可以仅仅修改 datatype 后 reload.

3. (备选, 但更不推荐)移除 loadonce:false, 调整成loadonce:true (只适用于数据量小的情况)

如果数据量不大,可以考虑将loadonce 设置为 true。 第一次加载后,后续的操作都是在本地(浏览器)进行。

  • 原理 : 第一次从服务器获取所有数据,之后所有排序、分页、筛选操作都在客户端完成,不再向服务器发送请求。 更新完数据, 仅需重新渲染。

  • 代码示例:

    // 在 jqGrid 初始化部分,把loadonce设置为true
     $grid.jqGrid({
    //其他属性....
     loadonce:true,
     //....其他属性
    })
    

    修改 successfunc 部分的代码:

        successfunc: function (response) {
          if(response.responseText == "true"){
              // 如果是 loadonce: true 模式, 可以在成功后手动刷新表格的 data
              var grid = $("#list")[0]; // 获取 grid 对象
                  grid.addJSONData(response.newData); //这里需要服务器配合返回新的rowData, 这比较麻烦.
                  // 或者尝试 $("#list").trigger("reloadGrid"); 也可以尝试是否有效(但不一定)
              return true;
          }
        }
    
    
  • 说明: 此方法需要调整服务器端的返回格式,需要 response 里带上修改后的行数据(newData)。 操作较繁琐。且仅适用于数据集小,且不需要频繁与服务器交互的场景。

  • 重要提示 : 大部分场景不建议用此方案, 前两种更推荐.

安全建议

  • 输入验证: PHP 代码中,虽然使用了预处理语句(Prepared Statements),有效防止了 SQL 注入,但在处理用户输入时,仍然建议进行数据类型和格式的验证,例如验证 QuantityUnitPrice 是否为数字。
  • 错误处理: 建议在 PHP 代码中增加更详细的错误处理,例如使用 try...catch 块捕获 PDO 异常,记录详细错误信息,并向前端返回更友好的错误提示。
  • XSS 防护 : 确保用户输入的 Description 内容经过了适当的过滤或转义,防止跨站脚本攻击(XSS)。 JqGrid 本身输出数据时候会进行处理, 但良好的习惯是永远做好输入输出的处理。

进阶使用:

  1. 自定义错误处理: JqGrid 的 errorfunc 选项可以用来处理编辑过程中的错误。可以在 errorfunc 中显示自定义的错误消息,或者进行其他的错误处理操作。

  2. 本地数据编辑 (Client-side Editing): 对于小数据量的表格, 设置 datatype: "local" ,完全在客户端进行数据操作. 更复杂的使用也可以结合 data 选项来实现预先加载一部分,后续更新部分数据的更复杂的操作.

  3. 优化数据加载 : 数据量大的表格,优化数据加载可以显著的提高性能, 利用jqGrid提供的gridview:true来提速. gridview:true的作用是让jqGrid先构建好整个HTML再添加到页面DOM树里。而不是逐行添加DOM节点。这样一次性的添加到DOM中要快。

希望上面几个解决办法能帮你解决表格数据更新问题! 记住,trigger("reloadGrid") 通常是解决这类问题的最直接、最有效的手段。 根据实际情况,你还可以结合使用 setGridParam 来灵活地控制表格的重新加载行为.