From aa5f0af6dc340fecda0bf32509ddd3ecb8f00008 Mon Sep 17 00:00:00 2001 From: Eric Lipe Date: Tue, 20 Aug 2024 17:24:33 -0400 Subject: [PATCH] - Working mutliselect with "apply filters" button - parsing query out of query string for list filters --- .../admin_interface/508/dropdown-filter.js | 53 ++++++++++--------- .../admin_interface/dropdown_filter.html | 2 +- django508/tests/admin/dummies.py | 8 +-- 3 files changed, 30 insertions(+), 33 deletions(-) diff --git a/admin_interface/static/admin_interface/508/dropdown-filter.js b/admin_interface/static/admin_interface/508/dropdown-filter.js index 82e964f..0115ef2 100644 --- a/admin_interface/static/admin_interface/508/dropdown-filter.js +++ b/admin_interface/static/admin_interface/508/dropdown-filter.js @@ -5,47 +5,48 @@ if (typeof (django) !== 'undefined' && typeof (django.jQuery) !== 'undefined') { 'use strict'; $(document).ready(function () { const filters = document.querySelectorAll('#changelist-filter .list-filter-dropdown select') - let query = '' - let multiQuery = '' - // Override the default onchange handler of each filter - for (const filter of filters) { - // This needs to be a function expression so `this` references the filter elements themselves - if (!filter.ariaMultiSelectable) { - filter.onchange = function() { - let value = this.options[this.selectedIndex].value - if (query !== '') { - value = value.replace('?', '&') - } - query = query.replace(multiQuery, '') - query = query.concat(value) - }; - } - } + let query = '?' const applyFiltersButton = document.querySelector('#submit-filters'); if (applyFiltersButton) { applyFiltersButton.onclick = function () { for (const filter of filters) { - if (filter.ariaMultiSelectable) { + let conjunction = query === '?' ? '' : '&' + if (!filter.ariaMultiSelectable) { + if (filter.selectedIndex !== 0) { + // Built in Django filters append the query string to the `value` field on the element. However, when we + // have a mult-selectable filter, the select element can't have the `value` field as a query string + // because multiple options can be selected and there is no way to track that. Therefore, we strip the + // single select filters query param from the existing query string and build and entirely new query + // string from that. + let opt = filter.options[filter.selectedIndex] + let query_str = opt.value + let filter_query = '' + for (let i = 1; i < query_str.length; i++) { + if (query_str[i] === '&') { + break + } + filter_query += query_str[i] + } + query = query.concat(conjunction, filter_query) + } + } + else { + // All multi select filters are required to set the `key` and `value` fields on the option element to the + // individual options to be able to build the correct query string. let selected = '' for (const option of filter.options) { if (option.selected) { - selected = selected.concat(option.value, '%2C') // Using the hex code for comma is what makes it work! + selected = selected.concat(option.value, '%2C') } } selected = selected.replace(/,+$/, "") - if (query === '' && multiQuery === '') { - multiQuery = multiQuery.concat('?') - } if (selected !== '') { - let param = multiQuery === '?' ? '' : '&' - multiQuery = multiQuery.concat(param, filter.options[0].getAttribute('key'), '=', selected) + query = query.concat(conjunction, filter.options[0].getAttribute('key'), '=', selected) } } } - console.log(query) - console.log(multiQuery) - window.location = query + multiQuery + window.location = query }; } }); diff --git a/admin_interface/templates/admin_interface/dropdown_filter.html b/admin_interface/templates/admin_interface/dropdown_filter.html index 162d59f..1998a04 100644 --- a/admin_interface/templates/admin_interface/dropdown_filter.html +++ b/admin_interface/templates/admin_interface/dropdown_filter.html @@ -5,7 +5,7 @@

{% blocktrans with title as filter_title %} By {{ filter_title }} {% endbloc
diff --git a/django508/tests/admin/dummies.py b/django508/tests/admin/dummies.py index a717c19..afb23ac 100644 --- a/django508/tests/admin/dummies.py +++ b/django508/tests/admin/dummies.py @@ -1,5 +1,4 @@ from django.contrib import admin -from .filters import DummyModelNameFilter from .multi_select_dropdown import MultiSelectDropdownFilter @@ -37,10 +36,8 @@ class Dummy_Admin(ReadOnlyDummyMixin): ] list_filter = [ - # DummyModelNameFilter, ('name', MultiSelectDropdownFilter), - ('created', MultiSelectDropdownFilter), - "name" + "created" ] class Dummy2_Admin(ReadOnlyDummyMixin): @@ -55,8 +52,7 @@ class Dummy2_Admin(ReadOnlyDummyMixin): ] list_filter = [ - DummyModelNameFilter, ('name', MultiSelectDropdownFilter), - "name" + "created" ]