Skip to content

Commit a32659e

Browse files
authored
Add data-filter-params attribute to filters navbar (#5971)
1 parent 125f0ed commit a32659e

1 file changed

Lines changed: 69 additions & 20 deletions

File tree

src/resources/views/crud/inc/filters_navbar.blade.php

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,40 @@ function refreshDatatablesOnFilterChange(url, tableId = 'crudTable')
130130
// replace the datatables ajax url with new_url and reload it
131131
table.ajax.url(url).load();
132132
}
133-
}
133+
}
134+
135+
// Each filter navbar stores its own filter state in a `data-filter-params` attribute.
136+
// This is the source of truth for consumers (e.g. report scripts) — they read from
137+
// the navbar DOM element, not the browser URL. This supports future scenarios with
138+
// multiple independent filter navbars on the same page.
139+
// When there is only one navbar, the browser URL is also kept in sync as a convenience
140+
// (bookmarkable URLs, shareable links).
141+
document.addEventListener('backpack:filter:changed', function(event) {
142+
if (!event.detail || !event.detail.shouldUpdateUrl) return;
143+
144+
// Find the navbar that owns this filter
145+
var componentId = event.detail.componentId || '';
146+
var navbar = componentId
147+
? document.querySelector('.navbar-filters[data-component-id="' + componentId + '"]')
148+
: document.querySelector('.navbar-filters');
149+
150+
if (!navbar) return;
151+
152+
// Update the navbar's stored filter state
153+
var params = new URLSearchParams(navbar.getAttribute('data-filter-params') || '');
154+
if (event.detail.filterValue !== '' && event.detail.filterValue != null) {
155+
params.set(event.detail.filterName, event.detail.filterValue);
156+
} else {
157+
params.delete(event.detail.filterName);
158+
}
159+
navbar.setAttribute('data-filter-params', params.toString());
160+
161+
// Mirror to the browser URL only when there is a single filter navbar
162+
if (document.querySelectorAll('.navbar-filters').length <= 1) {
163+
var newUrl = addOrUpdateUriParameter(window.location.href, event.detail.filterName, event.detail.filterValue);
164+
window.history.replaceState({}, '', newUrl);
165+
}
166+
});
134167
135168
// button to remove all filters
136169
document.addEventListener('DOMContentLoaded', function () {
@@ -151,6 +184,19 @@ function refreshDatatablesOnFilterChange(url, tableId = 'crudTable')
151184
return;
152185
}
153186
187+
// Seed the navbar's data-filter-params from the URL, scoped to this navbar's own filters.
188+
// This lets consumers read filter state from the navbar DOM element from the start,
189+
// and ensures shared URLs with filter params are applied correctly on load.
190+
var urlParams = new URLSearchParams(window.location.search);
191+
var navbarParams = new URLSearchParams();
192+
filters.forEach(function(filter) {
193+
var filterName = filter.getAttribute('filter-name');
194+
if (urlParams.has(filterName)) {
195+
navbarParams.set(filterName, urlParams.get(filterName));
196+
}
197+
});
198+
navbar.setAttribute('data-filter-params', navbarParams.toString());
199+
154200
// Add event listener only once per navbar to avoid duplication
155201
if (!navbar.hasAttribute('data-filter-events-bound')) {
156202
navbar.setAttribute('data-filter-events-bound', 'true');
@@ -249,14 +295,7 @@ function refreshDatatablesOnFilterChange(url, tableId = 'crudTable')
249295
}
250296
}
251297
252-
document.dispatchEvent(new CustomEvent('backpack:filters:cleared', {
253-
detail: {
254-
navbar: navbar,
255-
filters: filters,
256-
tableId: tableId
257-
}
258-
}));
259-
298+
// 1. Clear each filter's UI state
260299
filters.forEach(function(filter) {
261300
filter.dispatchEvent(new CustomEvent('backpack:filter:clear', {
262301
detail: {
@@ -265,7 +304,27 @@ function refreshDatatablesOnFilterChange(url, tableId = 'crudTable')
265304
}));
266305
});
267306
268-
// After clearing filters, re-initialize them to ensure proper state
307+
// 2. Clear the navbar's stored filter state and clean the browser URL
308+
navbar.setAttribute('data-filter-params', '');
309+
if (document.querySelectorAll('.navbar-filters').length <= 1) {
310+
let cleanUrl = URI(window.location.href).search('').toString();
311+
if (window.crud && typeof window.crud.updateUrl === 'function') {
312+
window.crud.updateUrl(cleanUrl);
313+
} else {
314+
window.history.replaceState({}, '', cleanUrl);
315+
}
316+
}
317+
318+
// 3. Notify consumers that all filters have been cleared
319+
document.dispatchEvent(new CustomEvent('backpack:filters:cleared', {
320+
detail: {
321+
navbar: navbar,
322+
filters: filters,
323+
tableId: tableId
324+
}
325+
}));
326+
327+
// 4. Re-initialize filters to ensure proper state
269328
setTimeout(function() {
270329
filters.forEach(function(filter) {
271330
let initFunction = filter.getAttribute('filter-init-function');
@@ -274,16 +333,6 @@ function refreshDatatablesOnFilterChange(url, tableId = 'crudTable')
274333
}
275334
});
276335
}, 50);
277-
278-
// Force update the URL to remove all filter parameters after a short delay
279-
// to ensure all filters have processed the clear event
280-
setTimeout(function() {
281-
let currentUrl = window.location.href;
282-
let cleanUrl = URI(currentUrl).search('').toString();
283-
if (window.crud && window.crud.updateUrl) {
284-
window.crud.updateUrl(cleanUrl);
285-
}
286-
}, 100);
287336
});
288337
}
289338

0 commit comments

Comments
 (0)