DataTable rows.every 函数问题

DataTable rows.every function Issue

我正在使用 jQuery DataTables 插件创建出勤跟踪器!我对 functionality/capability 的了解已经很深了,并且已经被困了数周,试图弄清楚如何完成我希望它完成的最后一部分。

我将在下面附上一个 static/workable 测试用例。所以我无法弄清楚的问题是如何根据子行单元格值设置父行的样式。 Sunday-Friday 列根据名为 SundayStatus、MondayStatus、TuesdayStatus 等的隐藏值进行着色。有两个值可以使它变绿(TW 和 P),两个值可以使它变黄(NR 和 O),还有两个值可以使它变红(PTO 和 H)。在我的 rows.every(function ( rowIdx, tableLoop, rowLoop ) { 函数中,我需要找到一种方法来操作数据并根据每天的出勤值将 classes 添加到父行。

P.S。(我创建了自己的插件 $.fn.dataTable.ext.search.push(function 来搜索 table 中的所有数据,并且仅显示日期为周日至周五的项目在本周。

UPDATE 5/10 Andrew 在更新他的答案时走在了正确的轨道上,我对今天的格式做了一个小改动, 并将 var result = Object.keys(data).find(key => data[key].substring(0,10) === today); 更改为 var result = Object.keys(data).find(key => typeof data[key] === 'string' && data[key].startsWith(today));。然后,我在我的动态代码中创建了一个条件,以读取反向查找的结果,并根据结果为该行着色。

这是我之前在 post 中的一个片段中的静态示例的 JSFiddle:https://jsfiddle.net/BeerusDev/y8t0xoze/19/

在这次更新中,我要处理的最后一个也是最后一个我没有预见到的问题是,一切似乎都运行良好,但它附加了第一个项目的状态 class post编辑到 DataTable 并且不考虑其他项目。我在试图找出解决此问题的方法时遇到了心理障碍,但这是我的动态应用程序中的 rows.every 函数,它位于我的 startRender 函数

var statusClass = '';
                    rows.every(function ( rowIdx, tableLoop, rowLoop ) {
                    var data = this.data();

                    var node = this.node();

                    var today = moment().format("YYYY-MM-DD"); // "05/10/2021"
                    console.log(today);
                    
                    //console.log(JSON.stringify(data));

                    var result = Object.keys(data).find(key => typeof data[key] === 'string' && data[key].startsWith(today)); // "Monday"
                    console.log(result);

                    var todayStatus = result ? data[result + 'Status'] : 'n/a'; 
                    console.log(todayStatus);
                    
                        if(todayStatus === "P" || todayStatus === "TW") {
                            statusClass = 'green';
                        }
                        if(todayStatus === "NR" || todayStatus === "O") {
                            statusClass = 'yellow';
                        }
                        if (todayStatus === "PTO" || todayStatus === "H") {
                            statusClass = 'red';
                        }
                    });
                    //Add category name to the <tr>.   
                        return $('<tr/>').addClass(statusClass)
                        .append('<td colspan="8">' + group + ' (' + rows.count() + ')</td>')
                        .attr('data-name', all)
                        .toggleClass('collapsed', collapsed);

这对我来说非常接近!

以下是我推荐的一些更改:

  1. 结束 </table> 标签后,还有一个额外的 <body> 标签。这看起来不正确 - 它应该被删除。我认为这不会导致任何错误 - 但值得修复。

  2. 在您的 rows.every() 函数中,data 变量是一个普通数组 - 例如:

    [“IT”、“姓名 1”、“此处位置”、“05/02/2021”、“05/03/2021”、“P”、...]

因此您不能使用 data.MondayStatus - 因为那将是 undefined。而是使用 data[5] 之类的东西来获取数组中的第 6 项 (P).

  1. 如果您想更改某个位置(例如“IT”或“OM”)的行的背景颜色,您可以使用这样的选择器:

    $("tr[数据名称='IT'] td").addClass("绿色");

之所以有效,是因为您已经将名为 data-name 的自定义属性添加到相关的 <td> 标记中。选择器找到 <td> 标签,它是使用该自定义属性的 <tr> 标签的子标签。

但是,这里的问题是:您正在尝试将 class 分配给 table 节点 ,然后 DataTable 已完成构建。

要解决此问题,您可以将所有行循环逻辑移至 initComplete 函数:

initComplete: function(settings, json) {
  this.api().rows().every(function ( rowIdx, tableLoop, rowLoop ) {
    var data = this.data();
    var node = this.node().previousSibling; // to handle your row grouping
    if (node !== null) {
      if (data[5] === "P") {
        var selectorVar = "[data-name='" + data[0] + "'] td";                       
        $( selectorVar ).addClass("green");
      }
    }
  });
}

而不是 if (data[5] === "P"),您可以扩展此逻辑以处理不同的值和不同的 class 名称(不仅仅是“绿色”),无论您需要什么整体逻辑。我的逻辑只是一个展示颜色变化的小demo。


更新以处理“今天”

为了展示该方法,我们假设以下记录:

var data = {  
  "Department": "IT",
  "Name": "Name 1",
  "Locations": "Locations Here",
  "Sunday": "2021-05-09",
  "Monday": "2021-05-10",
  "MondayStatus": "P",
  "Tuesday": "2021-05-11",
  "TuesdayStatus": "Q",
  "Wednesday": "2021-05-12",
  "WednesdayStatus": "R",
  "Thursday": "2021-05-13",
  "ThursdayStatus": "S",
  "Friday": "2021-05-14",
  "FridayStatus": "T"
};

这个 data 变量就是我认为您在 rows.every 函数中处理的变量。所以,它相当于 var data = this.data();。我可能弄错了一些键 (uppercase/lowercase) - 但如果是这种情况,您可以调整测试数据。

现在,我得到今天的日期,其格式与 data 对象中的日期格式相匹配:

var today = moment().format("YYYY-MM-DD"); // "2021-05-10"

我使用此值在 data 变量中查找等效值,并且我 return 该条目的键名:

var result = Object.keys(data).find(key => data[key].substring(0,10) === today); // "Monday"

这基本上是您通常所做的反向查找。我们不是以键开头,而是以值开头并以键结束 - 在本例中,键是字符串“Friday”。

现在我们获取此字符串并在其后附加“Status”。

这给了我们一个实际的关键字符串:“FridayStatus”。

现在我们使用该键查找今天的状态(如果它存在于 data 对象中):

var todayStatus = result ? data[result + 'Status'] : 'n/a'; // "P"

如果日期不存在,那么您最终的状态将是“n/a”。

总的来说,这为我们提供了一种快速获取今天状态的方法,而无需执行大量 if/else 逻辑。

获得今天的状态后,您可以在较小的 if/else 中使用它来选择要应用到该行的所需颜色。