Фильтр Tablesorter's filter_selectSource удаляет параметры, недоступные для текущей страницы с разбиением на страницы на стороне сервера, и выбирает подготовку параметров - PullRequest
1 голос
/ 08 июля 2019

Я готовлю массивы с опциями для filter_selectSource Tablesorter в Python / Django.Потому что изначально, для меня это работало очень странно, когда я переключился на фильтрацию на стороне сервера.Параметры раскрывающегося списка отображались только в том случае, если я набрал один символ в одном из фильтров поиска, а затем каждый раз, когда показывались варианты выбора, доступные на шаг раньше.И тогда я решил попытаться сделать большую часть работы на стороне сервера

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_selectSource и getOptions .Не могу найти то, что я хочу.

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);
  });

Я также записываю selectOptions во внешний файл .js, чтобы убедиться, что получаю то, что ожидается.

ОБНОВЛЕНИЕ.Я пытался заставить его работать с buildSelect, как предложил @Mottie в комментарии.Как оказалось, filter_selectSource actall 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, вызывающем огромное количество обновлений таблицы.Но без этого опции для выпадающих меню пусты.Я пытался связать это обновление для различных событий .Как 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 Ответ

1 голос
/ 10 июля 2019

С помощью Мотти Я смог решить проблему.

Мне не нужно было запускать обновления. Просто загрузите параметры из обратного вызова AJAX, используя функцию buildSelect. Итак, полный скрипт, который заставляет выбранные фильтры работать должным образом, выглядит следующим образом:

$("#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'
      },
    });

UPDATE. Я на самом деле только что выяснил, почему это решение не работает, как ожидалось, в некоторых случаях. Я забыл добавить filter_selectSource : { ".filter-select" : function() { return null; } }, к widget-options. Без функции, возвращающей ноль, filter_selectSource пытался переопределить опции, сделанные buildSelect. Я отредактировал код.

...