在数据表 jquery 的单列中创建月年自定义搜索

问题描述 投票:0回答:1

我有一个表格,其页脚的每一列中都有搜索栏。每列的搜索都按预期进行。但当它出现在日期这一栏时,问题就来了。

我当前的日期格式是

"mm/dd/yyyy"

当我尝试输入

"mm/yyyy"
例如
"03/2023"
时,我会得到带有日年
"dd/yyyy"
的值,如
["01/03/2023","02/03/2023", "04/03/2023"]
。这不是我想要的,因为我想获取给定月份和年份内的所有日期。

所以我尝试使用数据表中的

DataTable.ext.search.push
函数。首先,我想保留全局搜索,所以我包括:

 if (inputData === '') {
    return true;
}

然后我想过滤给定的格式为

"mm/yyyy"
的输入是否有效以及年份或月份是否等于输入。

return (
     isValidDate(inputData, 'MM/yyyy') &&
     inputDate.year === rowDate.year ||
     inputDate.month === rowDate.month
);

这个逻辑给了我同样的问题,其中

"dd/yyyy"
数据没有显示
"mm/yyyy"
如何修复我的逻辑或代码以便过滤正确的数据?我尝试询问 chatGPT,但它表明了相同的逻辑和相同的结果。另外,如果有更好的方法来过滤或重构我的代码,请随时提出建议。

有关更多上下文,这里是我当前代码的更大片段。

            $('.table-resize tfoot th').each(function(i) {
                if (headerLen - 1 != i) {
                    var title = $('.table-resize thead th').eq(i).text();
                    $(this).html(
                        '<div class="form-group"><input class="form-control ' + (title ==
                            'Date Sourced' ? 'ds_search' : '') + '" type="text" placeholder="' +
                        title +
                        '" data-index="' + i + '" /></div>');
                }

            });
            table = $('.table-resize').DataTable({
                scrollY: "500px",
                scrollX: true,
                scrollCollapse: true,
                scrollResize: true,
                pageResize: true,
                fixedColumns: {
                    leftColumns: 5,
                },
                drawCallback: function(settings) {
                    $('.table-loading-cont').removeClass('d-flex').css('display', 'none')
                    $('.table-resize').removeClass('d-none')
                    resizeTable()
                }
            });

            $(table.table().container()).on('keyup change', 'tfoot input', function() {
                table
                    .column($(this).data('index'))
                    .search(this.value)
                    .draw()
            });

            DataTable.ext.search.push(function(settings, data, dataIndex) {
                var searchData = data[1];
                var inputData = $($('tfoot .ds_search')[1]).val();

                if (inputData === '') {
                    return true;
                }

                var inputDate = getDate(inputData, 'MM/yyyy');
                var rowDate = getDate(searchData);

                return (
                    isValidDate(inputData, 'MM/yyyy') &&
                    inputDate.year === rowDate.year ||
                    inputDate.month === rowDate.month
                );
            });

编辑:

我找到了解决方法。我将从列搜索中获取月份,并在全局搜索中获取年份。

DataTable.ext.search.push(function(settings, data, dataIndex) {
                var searchData = data[1];
                var inputData = $($('tfoot .ds_search')[1]).val();

                if (inputData == '' ||
                    isValidDate(inputData) ||
                    (inputData.length == 2 && parseInt(inputData) == getDate(searchData).month)
                ) {
                    return true;
                }

                return false;
            });

这个解决方案给了我预期的输出。然而,这对于用户来说并不直观,因为用户会同时使用 2 个搜索栏。所以现在的问题是:是否有更好的方法只需要从列搜索栏中输入一个即可完成此操作?

javascript jquery datatables
1个回答
0
投票

这是一个最小示例,基于以下代码:https://datatables.net/examples/api/multi_filter.html

搜索“03/2023”时,会得到“01/03/2023”、“02/03/2023”和“04/03/2023”。

new DataTable('#example', {
  initComplete: function() {
    this.api()
      .columns()
      .every(function() {
        let column = this;
        let title = column.footer().textContent;

        // Create input element
        let input = document.createElement('input');
        input.placeholder = title;
        column.footer().replaceChildren(input);

        // Event listener for user input
        input.addEventListener('keyup', () => {
          if (column.search() !== this.value) {
            column.search(input.value).draw();
          }
        });
      });
  }
});
tfoot input {
  width: 100%;
  padding: 3px;
  box-sizing: border-box;
}
<link href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.7.0.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<table id="example" class="display" style="width:100%">
  <thead>
    <tr>
      <th>Name</th>
      <th>Position</th>
      <th>Office</th>
      <th>Age</th>
      <th>Start date</th>
      <th>Salary</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tiger Nixon</td>
      <td>System Architect</td>
      <td>Edinburgh</td>
      <td>61</td>
      <td>04/03/2023</td>
      <td>$320,800</td>
    </tr>
    <tr>
      <td>Garrett Winters</td>
      <td>Accountant</td>
      <td>Tokyo</td>
      <td>63</td>
      <td>01/03/2023</td>
      <td>$170,750</td>
    </tr>
    <tr>
      <td>Ashton Cox</td>
      <td>Junior Technical Author</td>
      <td>San Francisco</td>
      <td>66</td>
      <td>02/03/2023</td>
      <td>$86,000</td>
    </tr>
    <tr>
      <td>Cedric Kelly</td>
      <td>Senior Javascript Developer</td>
      <td>Edinburgh</td>
      <td>22</td>
      <td>03/29/2023</td>
      <td>$433,060</td>
    </tr>
    <tr>
      <td>Airi Satou</td>
      <td>Accountant</td>
      <td>Tokyo</td>
      <td>33</td>
      <td>03/28/2023</td>
      <td>$162,700</td>
    </tr>
    <tr>
      <td>Brielle Williamson</td>
      <td>Integration Specialist</td>
      <td>New York</td>
      <td>61</td>
      <td>12/02/2023</td>
      <td>$372,000</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th>Name</th>
      <th>Position</th>
      <th>Office</th>
      <th>Age</th>
      <th>Start date</th>
      <th>Salary</th>
    </tr>
  </tfoot>
</table>

解决方案

遵循 https://datatables.net/examples/api/regex.html,此解决方案通过将“MM/YYY”形式的类似日期的文本转换为正则表达式,在内部使用自定义正则表达式搜索。

当用户在这个新搜索框中键入“03/2023”时,输入文本将转换为正则表达式

03\d{2}2023
,并且此搜索的结果是开始日期为“03/28/2023”和“03”的记录/29/2023”。

let table = new DataTable('#example', {
  initComplete: function() {
    this.api()
      .columns()
      .every(function() {
        let column = this;
        let title = column.footer().textContent;
        // Create input element
        let input = document.createElement('input');
        input.placeholder = title;
        column.footer().replaceChildren(input);
        // Event listener for user input
        input.addEventListener('keyup', () => {
          if (column.search() !== this.value) {
            column.search(input.value).draw();
          }
        });
      });
  }
});


function isValidDate(value) {
  // matches 1/2023, 01/2023, 1/3/2023, 01/03/2023, etc.
  return /^\d{1,2}(\/\d{1,2})?\/\d{4}$/.test(value)
}

function filterColumn(table, i) {
  let filter = document.querySelector('#col' + i + '_filter');
  let regex = document.querySelector('#col' + i + '_regex');
  if (isValidDate(filter.value) && filter.value.length < 8) {
    // form regular expression from MM/YYYY
    let myRegex = filter.value.split('/').join('/\\d{2}/');
    console.log("Search for matching:", myRegex);
    table.column(i).search(myRegex, regex = true).draw();
  } else {
    table.column(i).search(filter.value).draw();
  }
}

document.querySelectorAll('input.column_filter').forEach((el) => {
  let tr = el.closest('tr');
  let columnIndex = tr.getAttribute('data-column');
  el.addEventListener(el.type === 'text' ? 'keyup' : 'change', () =>
    filterColumn(table, columnIndex)
  );
});
tfoot input {
  width: 100%;
  padding: 3px;
  box-sizing: border-box;
}
<link href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.7.0.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<table cellpadding="3" cellspacing="0" border="0" style="width: 50%; margin: 0 auto 2em auto;">
  <tbody>
    <tr id="filter_col5" data-column="4">
      <td><b>Search by month MM/YYYY</b></td>
      <td align="center"><input type="text" class="column_filter" id="col4_filter"></td>
    </tr>
  </tbody>
</table>
<table id="example" class="display" style="width:100%">
  <thead>
    <tr>
      <th>Name</th>
      <th>Position</th>
      <th>Office</th>
      <th>Age</th>
      <th>Start date</th>
      <th>Salary</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tiger Nixon</td>
      <td>System Architect</td>
      <td>Edinburgh</td>
      <td>61</td>
      <td>04/03/2023</td>
      <td>$320,800</td>
    </tr>
    <tr>
      <td>Garrett Winters</td>
      <td>Accountant</td>
      <td>Tokyo</td>
      <td>63</td>
      <td>01/03/2023</td>
      <td>$170,750</td>
    </tr>
    <tr>
      <td>Ashton Cox</td>
      <td>Junior Technical Author</td>
      <td>San Francisco</td>
      <td>66</td>
      <td>02/03/2023</td>
      <td>$86,000</td>
    </tr>
    <tr>
      <td>Cedric Kelly</td>
      <td>Senior Javascript Developer</td>
      <td>Edinburgh</td>
      <td>22</td>
      <td>03/29/2023</td>
      <td>$433,060</td>
    </tr>
    <tr>
      <td>Airi Satou</td>
      <td>Accountant</td>
      <td>Tokyo</td>
      <td>33</td>
      <td>03/28/2023</td>
      <td>$162,700</td>
    </tr>
    <tr>
      <td>Brielle Williamson</td>
      <td>Integration Specialist</td>
      <td>New York</td>
      <td>61</td>
      <td>12/02/2023</td>
      <td>$372,000</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th>Name</th>
      <th>Position</th>
      <th>Office</th>
      <th>Age</th>
      <th>Start date</th>
      <th>Salary</th>
    </tr>
  </tfoot>
</table>

© www.soinside.com 2019 - 2024. All rights reserved.