使用复选框控制DataTables列的可见性

时间:2019-06-27 20:50:01

标签: javascript php jquery laravel datatables

我正在使用在刀片模板上动态呈现表格。我有一系列复选框,用户可以检查它们以显示/隐藏表列。所有这一切都很好。

这是我的模板的样子:

template.blade.php

<table id="dataTables-report" class="table table-striped table-bordered table-hover">
</table>

这是我用来呈现表格的内容:

scripts.js

$('#dataTables-report').DataTable({
  ...
  columnDefs: [
      {
          targets: 0,
          title: 'Name',
          searchable: true,
          data: function (row, type, val, meta) {
              // return row.data;
          }
      },
      @if($report->order_date)
            {
                targets: 1,
                title: 'Order Date',
                searchable: false,
                data: function (row, type, val, meta) {
                    // return row.data;
                }
            },
       @endif
       @if($report->order_number)
            {
                targets: 2, // could be 1 if order date is not selected
                title: 'Order Number',
                searchable: false,
                data: function (row, type, val, meta) {
                    // return row.data;
                }
            },
       @endif
      ...
});

“订购日期”是用户可以选择在表格上显示的复选框。如果选中,它将显示该列。否则就不会。 可能会先选择其他列,并且可能是targets: 1。现在,如果用户选中另一个框,则targets需要动态设置为下一个数字。在这种情况下:targets: 2

每个复选框都作为其自己的列存储在数据库中,因此我认为我无法进行任何形式的循环(因此会生成许多if语句)。否则,我认为something like this会起作用。

有没有一种方法可以在我的刀片服务器模板中动态生成targets数字?

3 个答案:

答案 0 :(得分:0)

感谢您的建议,这是我在进一步研究您的建议时提出的“快速”解决方案。

在刀片模板中,我创建了一个全局变量,该变量可以在php中访问。

@section('scripts')
    <script>
        $(function () {
            ...
            let columnTarget = 0;

            ...

            $('#dataTables-report').DataTable({
                ...
               columnDefs: [
               {
                   targets: columnTarget,
                   title: 'Name',
                   searchable: true,
                   data: function (row, type, val, meta) {
                       // return row.data;
               }
           },
           @if($report->order_date)
           {
               targets: ++columnTarget,
               title: 'Order Date',
               searchable: false,
               data: function (row, type, val, meta) {
                  // return row.data;
               }
           },
           @endif
           @if($report->order_number)
           {
               targets: ++columnTarget,
               title: 'Order Number',
               searchable: false,
               data: function (row, type, val, meta) {
                // return row.data;
               }
           },
           @endif
         ...
    </script>
@endsection

这似乎运作良好;正确地(动态地)分配了targets值。

答案 1 :(得分:0)

如果您正在寻求由复选框控制的真正动态的列可见性(据我了解,您的最终目标),则可以完全通过几行jQuery在用户端完成。

为此,您可以简单地

  • 将每个列的源对象属性作为value属性附加到您的<input>节点:
  • change事件中,找到由与单击的复选框值相对应的对象属性派生的列(使用column().dataSrc()方法)并调整该列的可见性(相应地使用.column().visible()方法) :
$('#checkboxWrapper').on('change', '[type="checkbox"]', event => {
  let colindex = null;
  dataTable.columns().every(function(){
    if(this.dataSrc() == $(event.target).val()) colindex = this.index();
  });
  dataTable.column(colindex).visible($(event.target).prop('checked')).draw();
});

完整的实时演示,您可能会在下面找到:

//sample source data
const dataSrc = [
  {id: 1, item: 'apple', cat: 'fruit'},
  {id: 2, item: 'carrot', cat: 'vegie'},
  {id: 3, item: 'banana', cat: 'fruit'}
];

//extract all unique object keys from data source array
const checkboxes = [...new Set(dataSrc
  .map(item => Object.keys(item))
  .flat())];
//translate those into <input> nodes HTML
const checkboxesHtml = checkboxes.reduce((inputs, prop) => inputs += `<input type="checkbox" value="${prop}" checked>${prop}</input>`,'');
$('#checkboxWrapper').append(checkboxesHtml);

//initialize datatables
const dataTable = $('#example').DataTable({
  data: dataSrc,
  dom: 't',
  columns: checkboxes.map(prop => ({title: prop, data: prop}))
});

//control columns visibility with checkboxes
$('#checkboxWrapper').on('change', '[type="checkbox"]', event => {
  //grab column().index() that corresponds to checkbox value
  let colindex = null;
  dataTable.columns().every(function(){
    if(this.dataSrc() == $(event.target).val()) colindex = this.index();
  });
  //toggle selected column visibility
  dataTable.column(colindex).visible($(event.target).prop('checked')).draw();
});
<!doctype html>
<html>
<head>
  <script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  <script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
  <div id="checkboxWrapper"></div>
  <table id="example"></table>
</body>
</html>

答案 2 :(得分:0)

public static DateTimeOffset ToDateTimeOffset(this DateTime dt, TimeZoneInfo tz)
{
    if (dt.Kind != DateTimeKind.Unspecified)
    {
        // Handle UTC or Local kinds (regular and hidden 4th kind)
        DateTimeOffset dto = new DateTimeOffset(dt.ToUniversalTime(), TimeSpan.Zero);
        return TimeZoneInfo.ConvertTime(dto, tz);
    }

    if (tz.IsAmbiguousTime(dt))
    {
        // Prefer the daylight offset, because it comes first sequentially (1:30 ET becomes 1:30 EDT)
        TimeSpan[] offsets = tz.GetAmbiguousTimeOffsets(dt);
        TimeSpan offset = offsets[0] > offsets[1] ? offsets[0] : offsets[1];
        return new DateTimeOffset(dt, offset);
    }

    if (tz.IsInvalidTime(dt))
    {
        // Advance by the gap, and return with the daylight offset  (2:30 ET becomes 3:30 EDT)
        TimeSpan[] offsets = { tz.GetUtcOffset(dt.AddDays(-1)), tz.GetUtcOffset(dt.AddDays(1)) };
        TimeSpan gap = offsets[1] - offsets[0];
        return new DateTimeOffset(dt.Add(gap), offsets[1]);
    }

    // Simple case
    return new DateTimeOffset(dt, tz.GetUtcOffset(dt));
}