Tablesorter 的 filter_selectSource 使用服务器端分页和 select 选项准备删除当前页面不可用的选项

Tablesorter's filter_selectSource removes options not available for current page with server-side pagination and select options preparation

我正在为 Python/Django 中的 Tablesorter filter_selectSource 准备带有选项的数组。因为最初,当我切换到服务器端过滤时,它对我来说很奇怪。仅当我在 'search' 过滤器之一中键入一个符号时,下拉选项才会显示,然后每次显示前一步可用的 select 选项。 然后我决定尝试在服务器端完成大部分工作

players.views

def skaters_averages_json(request, page, sort_col, filt_col, rookie_filt):

    start = utils.PAGE_SIZE_2*(page - 1)
    end = start + utils.PAGE_SIZE_2
    skaters = Skater.objects.select_related('team')

    filtering = utils.filter_columns(filt_col)
    if filtering:
        skaters = utils.apply_filters(skaters, filtering)

    if utils.rookie_filter(rookie_filt):
        skaters = skaters.filter(rookie=True)

    sorting = utils.sorting_columns(sort_col)
    one_page_slice = utils.sort_table(sorting, skaters)[start:end]

    skaters_json = json.loads(serializers.serialize('json', one_page_slice,
                                                    use_natural_foreign_keys=True))
    domain = request.get_host()
    total_rows = skaters.count()
    data = utils.process_json(domain, skaters_json, total_rows, page)

    data['filter_select'] = {
        **utils.filter_select_opts(skaters, 3, 'position_abbr'),
        **utils.filter_select_opts(skaters, 4, 'team__abbr'),
        **utils.filter_select_opts(skaters, 5, 'nation_abbr'),
    }

    return JsonResponse(data, safe=False)

players.utils

def filter_select_opts(skaters_query, col_number, field_name):
    uniques = list(skaters_query.values_list(field_name, flat=True).distinct())
    return {col_number: sorted(uniques, key=lambda x: (x is None, x))}

所以我的 JSONResponse 看起来像这样。

第 1 页

{
  "total": 41,
  "rows": [
    [row 1],
    ...
    [row 25]
  ],

  "filter_select": {
    "3": [
      "C",
      "D",
      "LW",
      "RW"
    ],
    "4": [
      "ANA",
      "BOS",
      "BUF",
      "CAR",
      "CBJ",
      "CGY",
      "CHI",
      "COL",
      "DAL",
      "EDM",
      "FLA",
      "MIN",
      "MTL",
      "NJD",
      "NSH",
      "NYI",
      "PHI",
      "PIT",
      "SJS",
      "TOR",
      "VAN",
      "VGK",
      "WPG"
    ],
    "5": [
      "FIN"
    ]
  }
}

第 2 页

{
  "total": 41,
  "rows": [
    [row 26],
    ...
    [row 41]
  ],

  "filter_select": {
  "3": [
    "C",
    "D",
    "LW",
    "RW"
  ],
  "4": [
    "ANA",
    "BOS",
    "BUF",
    "CAR",
    "CBJ",
    "CGY",
    "CHI",
    "COL",
    "DAL",
    "EDM",
    "FLA",
    "MIN",
    "MTL",
    "NJD",
    "NSH",
    "NYI",
    "PHI",
    "PIT",
    "SJS",
    "TOR",
    "VAN",
    "VGK",
    "WPG"
  ],
  "5": [
    "FIN"
  ]
}
}

应用过滤器响应的第二页显示 filter_select 的相同值但是当我在 filter_selectSource 处理后查看相同的页面时,它仅显示当前可见的可用选项页。 有没有办法覆盖此行为?

阅读 filter_selectSourcegetOptions 的文档。找不到我想要的。

external.js

let selectOptions;

$("#tab1")
  .tablesorter({
      headers: {
          0: {sorter: false, filter: false},
          1: {filter: false},
          2: {filter: false},
      },

      widgets: ['filter'],
      widgetOptions : {
      filter_selectSource: selectOptions,
      filter_reset: '.reset',
      filter_external : '.select',
  }
})

.tablesorterPager({
    container: $(".pager-s"),
    size: 25,
    output: '{page} / {totalPages}',
    savePages: false,
    fixedHeight: false,
    ajaxUrl: 'http://127.0.0.1:8000/skaters_averages_json/{page+1}/{sort:col}/{filter:fcol}',
    customAjaxUrl: function(table, url) {
    if ($("#tab1").data('filter_value')) {
          return url += '/rookie_filter=' + $("#tab1").data('filter_value');
    };
        return url += '/rookie_filter=';
    },

    ajaxObject: {
        success: function(data) {
          selectOptions = data['filter_select'];
          $("#tab1").trigger("updateAll");
          console.log(selectOptions);
        },
        dataType: 'json',
        type: 'GET'
      },
    });

$('.rookie-filter').on('change', function(){
    let checked = $(this).is(":checked");
    $("#tab1").data('filter_value', checked).trigger('pagerUpdate', 1);
    if (checked) {
      $(this).attr('title', 'Show all players')
    } else {
      $(this).attr('title', 'Show rookies only')
    };
});

$('.reset').on('click', function(){
  $('.rookie-filter').prop('checked', false);
  $("#tab1").data('filter_value', $(this).is(":checked")).trigger('pagerUpdate');
});

$('table').bind("sortEnd", function(){
    $(this).trigger('pageSet', 1);
  });

我还在我的外部 .js 文件中记录 selectOptions 以确保我得到了预期的结果。

更新。 正如@Mottie 在评论中所建议的那样,一直在努力使其与 buildSelect 一起使用。 事实证明,filter_selectSource actualdidn't accept my variable infilter_selectSource: selectOptions, the only line that makes a difference is$("#tab1").trigger("updateAll")inajaxObject`。然后 Tablesorter 会自动显示当前页面上可用的选项。

所以,现在我正在努力触发筛选行的更新。 我能够一次加载一列的预期选项,但 table 不起作用,因为 too much recursion 错误。 $('body').trigger(filter_event) 在每个 filter_selectSource 中导致大量更新 table。但是没有它,下拉菜单的选项是空的。我尝试为不同的 events 绑定此更新。喜欢filterInit。没有为我工作。 看看下面我更新的脚本。关于如何让它更新过滤器行而不重复多次的任何建议?

$("#tab1").data('statType', 'tot');
let pos = [];
let team = [];
let nation = [];
let filter_event = jQuery.Event("load_filter_select");

$("#tab1")
  .tablesorter({
      headers: {
          0: {sorter: false, filter: false},
          1: {filter: false},
          2: {filter: false},
      },

      widgets: ['filter'],
      widgetOptions : {

        filter_selectSource: {
          3 : function(table, column, onlyAvail) {
            result = pos;
            $.tablesorter.filter.buildSelect(table, column, result, true);
            $('body').trigger(event);
          },

          4 : function(table, column) {
            result = team;
            $.tablesorter.filter.buildSelect(table, column, result, true);
            $('body').trigger(filter_event);
          },

          5 : function(table, column) {
            result = nation;
            $.tablesorter.filter.buildSelect(table, column, result, true);
            $('body').trigger(filter_event);
          },
        },

      filter_reset: '.reset',
      filter_external : '.select',
  }
})

.tablesorterPager({
    container: $(".pager-s"),
    size: 25,
    output: '{page} / {totalPages}',
    savePages: false,
    fixedHeight: false,
    ajaxUrl: 'http://127.0.0.1:8000/skaters_averages_json?/{page+1}/{sort:col}/{filter:fcol}',
    customAjaxUrl: function(table, url) {
      urlParts = url.split('?');
      url = urlParts[0] + `/${$("#tab1").data('statType')}` + urlParts[1];

      if ($("#tab1").data('filter_value')) {
            return url += '/rookie_filter=' + $("#tab1").data('filter_value');
      };
          return url += '/rookie_filter=';
    },

    ajaxObject: {
        success: function(data) {
          pos = data['filter_select'][3];
          team = data['filter_select'][4];
          nation = data['filter_select'][5];

          $('body').trigger(filter_event);

        },
        dataType: 'json',
        type: 'GET'
      },
    });

$('body').on('load_filter_select', function(){
    $("#tab1").trigger('update');
});

Mottie 的大力帮助下,我已经能够解决问题。

我不应该实际触发任何更新。只需使用 buildSelect 函数从 AJAX 回调加载选项。 因此,使 select 过滤器正常工作的完整脚本如下所示:

$("#tab1").data('statType', 'tot');

$("#tab1")
  .tablesorter({
      widgets: ['filter'],
      widgetOptions: {
          filter_selectSource : {
             ".filter-select" : function() { return null; }
          },

      }
})

.tablesorterPager({
    container: $(".pager-s"),
    size: 25,
    output: '{page} / {totalPages}',
    savePages: false,
    fixedHeight: false,
    ajaxUrl: 'http://127.0.0.1:8000/ajax_players?/{page+1}/{sort:col}/{filter:fcol}',
    customAjaxUrl: function(table, url) {
      urlParts = url.split('?');
      url = urlParts[0] + `/${$("#tab1").data('statType')}` + urlParts[1];

      if ($("#tab1").data('filter_value')) {
            return url += '/rookie_filter=' + $("#tab1").data('filter_value');
      };
          return url += '/rookie_filter=';
    },

    ajaxObject: {
        success: function(data) {
          table = $("#tab1");
          options = data['filter_select'];

          for (let column = 3; column <= 5; column++) {
              $.tablesorter.filter.buildSelect(table, column, options[column], true);
          };
        },
        dataType: 'json',
        type: 'GET'
      },
    });

更新。我实际上刚刚弄清楚为什么这个解决方案在某些情况下没有按预期工作。我忘了将 filter_selectSource : { ".filter-select" : function() { return null; } }, 添加到 widget-options。没有函数返回 null filter_selectSource 试图覆盖 buildSelect 所做的选项。我已经编辑了代码。