1. Create a new view (page display) based on a content type that has a field that references another content type
2. Add a filter to that entity reference field and expose it like shown in the screenshot
3. In the advanced section, set it to Use Ajax: True
4. Save the form
Now the page will have an exposed filter that is just a single checkbox. Since the form uses AJAX you can select or deselect the checkbox and submit and things will work as expected. However, the value for that checkbox could also be passed in through the URL if you know what to pass. For example: `/test-view?network[1]=1`. That would set the checkbox to be default selected. However, now if you unselect the checkbox and click submit, you'll see that it gets re-checked.
I've tracked this down to the ViewsAjaxController ajaxView method combining POST and GET values. The AJAX request sends all values through a POST, and the GET will have the values that are in the URL bar. This is not an issue for text fields or select dropdowns, because the values for those fields always get POSTed. So combining POST and GET values with the POST values having preference will work fine. However, with a checkbox, when the checkbox is unselected, no value is passed in POST, so it'll use what is in GET, which is saying that it is still selected.
I am not sure if there is a reason to join the POST and GET values together, or if it would be fine to just use POST values if they are provided, otherwise use GET. I will provide a possible patch to address it that way (knowing it might not be ideal). Another option would be to ensure that a blank value for unchecked checkboxes gets POSTed on AJAX submits.
| Comment | File | Size | Author |
|---|---|---|---|
| #3 | drupal-views-3160406-3.patch | 825 bytes | bdlangton |
| Screen Shot 2020-07-20 at 3.44.26 PM.png | 326.54 KB | bdlangton |
Comments
Comment #2
bdlangton commentedHere is a possible patch
Comment #3
bdlangton commentedUpdated patch
Comment #4
bdlangton commentedComment #6
berdirSeeing this as well. The problem is that ajax replicates the browser behavior of not explicitly sending a value for a non-checked checkbox and then then the one in the query string wins.
In my case, since I am setting the query string automatically through JS, I ended up updating the URL when you click it on the checkbox, but it's a pain, because I found at least 3 different places where the URL is stored and I'm not sure which ones are really used and where exactly.
Just updating the browser URL is not enough, I also had to update Drupal.views.instances.DOMID.element_settings.url, Drupal.ajax.instances.ID.url and Drupal.ajax.instances.ID.options.url. It is possible that only the last one really matters, no idea why views sets the URL twice. And no idea what element_settings is for.
Comment #7
neclimdulUgh, this really sucks. Facets and ajax views are problematic but this is definitely breaking that as well.
Despite being super hard to debug with those chrome requests, that failure seems to be legit. Media is using both query embed in the POST for pager but _also_ putting the MediaLibraryState into the QUERY query. So we've got logic that doesn't support checkboxes competing with code relying on the same logic.
I started writing a test but crashed Form API entirely so I'll come back with a test later.
Comment #9
claudiu.cristeaIsn't this a duplicate of #3121172: Exposed filters get values from url when ajax is on? I think so. I'll mark this as duplicate but feel free to revert it if I'm wrong.
Comment #10
claudiu.cristea