Tablesorter的filter_selectSource通过服务器端分页来删除当前页面不可用的选项,并准备选项

时间:2019-07-08 14:04:53

标签: jquery django ajax tablesorter

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

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,以确保获得期望的结果。

更新。 一直在尝试使其与buildSelect配合使用,如@Mottie在评论中建议的那样。 事实证明,filter_selectSource实际上didn't accept my variable in filter_selectSource:selectOptions , the only line that makes a difference is $(“#tab1”)。trigger(“ updateAll”)in ajaxObject`。然后,Tablesorter会自动显示当前页面上可用的选项。

因此,现在我正努力为过滤器行触发更新。 我能够一次加载一列的预期选项,但是由于too much recursion错误,该表无法正常工作。 每个$('body').trigger(filter_event)中的filter_selectSource导致大量更新表。但是没有它,下拉菜单的选项为空。我尝试将此更新绑定到其他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');
});

1 个答案:

答案 0 :(得分:1)

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

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

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

$("#tab1")
  .tablesorter({
      widgets: ['filter'],
})

.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'
      },
    });