It would be great to be able to select multiple items in a facet dropdown before applying the filter.

Issue fork facets-2811331

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

rocketeerbkw created an issue. See original summary.

rocketeerbkw’s picture

Status: Active » Needs work
StatusFileSize
new1.89 KB

This first patch turns the <select> into a multiple select when the facet setting "Make sure only one result can be shown" is disabled.

I haven't though about how to modify the javascript to accommodate selecting multiple options yet.

borisson_’s picture

+++ b/src/Plugin/facets/widget/DropdownWidget.php
@@ -32,6 +32,9 @@ class DropdownWidget extends WidgetPluginBase {
+    if (!$facet->getShowOnlyOneResult()) {
+      $build['#attributes']['class'][] = 'multiple-select';
+    }

I think the standard in core is to prefix this with `js-` if it's used in javascript to do things. Let's do that as well.

shkiper’s picture

Status: Needs work » Needs review
StatusFileSize
new1.8 KB

Here is separate 'Multiple select dropdown' widget

borisson_’s picture

I think I prefer the solution that @rocketeerbkw built in #2, it makes more sense to include this in the normal dropdown widget.

borisson_’s picture

Status: Needs review » Needs work

Back to needs work for #5.

a.milkovsky’s picture

Status: Needs work » Needs review
StatusFileSize
new2.02 KB

re-rolled #2

a.milkovsky’s picture

Yes, we should fix tests here as well.

borisson_’s picture

Status: Needs review » Needs work

Needs work to fix the test.

visios’s picture

I'd love to see multiple selects with checkboxes. Has anyone done this before with facets? When looking at faceted searches on the web, applying the filters to checkboxes and than submitting might be a more common use case than multiple select dropdown. Anyway, thanks to contributors for starting this one.

geek-merlin’s picture

Thanks all for working on this 💪 !

As @rocketeerbkw mentioned in #2:
> I haven't though about how to modify the javascript to accommodate selecting multiple options yet.

As soon as multiple options are selected, we are redirected to some url like example.com/[path1],[path2],[path3].

This is because val() returns an array then, which is to-stringified with comma separator.

This needs some work in this respect first...

geek-merlin’s picture

Status: Needs work » Needs review
StatusFileSize
new2.81 KB

Aaargh, i thin i did not have time for this but the problem was plain too interesting.😂

Patch flying in that implements the logic and worksforme in some simple tests. Beautifying the selects via Sumoselect works too.

Let's see what the bot says to the fixed test.

(BTW, can anybody explain me what the "empty text" option is supposed to do?)

geek-merlin’s picture

StatusFileSize
new3.69 KB

Hups, i forgot a hunk, no wonder test failed. Here comes the right patch.

geek-merlin’s picture

StatusFileSize
new3.69 KB

Strange that the last test run did not see this js error.
Fixed stupid error s/$this/$(this)/ and improved comment.

brunodbo’s picture

Thanks for working on this! I tested the patch in #14, and it works great when selecting one option at a time.

Since the window's location is changed when the select changes, it's currently not possible for a user to select multiple options at once, when using the multiselect facet in a desktop browser. When using the multiselect facet in a mobile browser (I was testing in Firefox on Android), the browser pops up its own select widget, allowing the user to select multiple options at once. In that case (i.e., if the user selects multiple options on mobile), once the page reloads, only one of the options that the user selected before reloading, will be selected.

I looked at how https://www.drupal.org/project/facetapi_multiselect did this in D7, since that has a 'Hide submit button' option in the facet's config. That module also listens for the change event, but does a JS submit() instead of changing the window's location directly.

brunodbo’s picture

Status: Needs review » Needs work
brunodbo’s picture

We could add a 'Filter' button, that we show or hide based on a config option. Then we can build the location string on each $dropdown change, and set the window location when the button is clicked (either by the user or by JS, depending on the facet's configuration).

Does that seem like a good approach?

geek-merlin’s picture

Status: Needs work » Reviewed & tested by the community

Currently the js gets with every option the URL to hit if that option is toggled. (So we have in fact the basic facet links, wrapped in a select widget)
I thought about the "select multiple and then submit" and i can't see a solution without a **complete** rewrite.

> Thanks for working on this! I tested the patch in #14, and it works great when selecting one option at a time.

So i'd propose to get this in and work on top of that in a followup.

brunodbo’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new3.36 KB

Just a small change to only pre-select the 'empty' option when it has a value set in the facet's configuration. Some multiselect libraries (e.g., Chosen) add their own 'empty value' text, and will show an empty selected option if there is one selected. So unless there is a reason to always pre-select the default option (also when it has no value), I'd propose we only pre-select it when it has a value.

hanness’s picture

@brunodbo

it's currently not possible for a user to select multiple options at once, when using the multiselect facet in a desktop browser. When using the multiselect facet in a mobile browser (I was testing in Firefox on Android), the browser pops up its own select widget, allowing the user to select multiple options at once.

For me this is an advantage of Facets, that people cannot get empty results and a disadvantage of the browser widgets on mobiles ;-)

And with Ajax Facets, which just got finished in the stable release of Facets on July 5, this works much faster now.

geek-merlin’s picture

@brunodbo

> it's currently not possible for a user to select multiple options at once, when using the multiselect facet in a desktop browser.

this current limitation should go to a separate issue. note that the the combination of >=2 facets might not be a facet (e.g. may be empty), so this needs more diskussion (apart from the technical issue i gave above).

> When using the multiselect facet in a mobile browser (I was testing in Firefox on Android), the browser pops up its own select widget, allowing the user to select multiple options at once.

we have this with some configurations of sumoselect and friends too.

geek-merlin’s picture

#19: while this might be a valid concern, it is related to chosen and friends and deserves its own discussion in a followup.

geek-merlin’s picture

Status: Needs review » Needs work

So imho we're back to #14, but this now fails to apply (seems like we missed a maintainer's timeframe), so back to NW.

brunodbo’s picture

Status: Needs work » Needs review
StatusFileSize
new3.5 KB

Yep, the fact that facets prevent a user from getting an empty result, is a great benefit (vs being able to select options that lead to a potential empty result). I do think we should eventually support the use case of selecting multiple options at once though, since mobile users don't have a choice but to use their device's select UIs for multiselects (as far as I know), and also because it's a standard behaviour of multiselects (deviating from this might have accessibility consequences). I'll open a follow up for that once this one goes in (I started working on it a few weeks ago, and it got messy quickly :) since it is tricky given how Facets currently works).

The change in #19 could move to a follow up as well, sure. Will open one when a reroll of #14 goes in.

Attaching a reroll of #14 here. I didn't test it with Ajax facets yet.

hanness’s picture

#24 works well with sumoselect and default dropdown.
however, when using ajax facets nothing happens when clicking on a facet item on current dev :/

but when i use the current dev without any multi select dropdown patch, it does work with ajax! (it also worked with beta2, as i tested today) it just does not show, which items i´ve selcted. but i can select multiple once. with sumoselect and with default dropdown.

so maybe we can use the default dropdown widget and just have to mark there, which items are currently selected, instead of a new multi select widget which might be hard to get working with the new ajax facets code?

hanness’s picture

Status: Needs review » Needs work
geek-merlin’s picture

I can confirm #25: The current single-select dropdown is plain misleading:
Remember that everything starts with facet links.
* If a facet is inactive, a click activates it.
* If a facet is active, we have a [-] before the link, and a click de-activates it.

The current single-select dropdown JS makes all (active and inactive) facets to select options, throwing away their in/active status.
This is broken by design. We might fix it like:
* Indicate if the facet is active (e.g. by prefixing ☑/☐)
* create a first, active option like "None selected" or "a+b+c selected"

So we mimick the link behavior with a widget that takes less visual space.
I tend to do that in a new issue.

geek-merlin’s picture

As of #24:
> I do think we should eventually support the use case of selecting multiple options at once though, since mobile users don't have a choice but to use their device's select UIs for multiselects (as far as I know), and also because it's a standard behaviour of multiselects (deviating from this might have accessibility consequences).

The approach in #27 would give us what was intenden here: See (possibly multiple) active facets in a single select dropdown and be able to drill down on them.

About drilling down facets client-side: This requires us to compute the whole tree of facet subsets and their respective query count, and needs some JS that visualizes that.

In the light of #27, do you think client-side multiselect is worth the quest?

brunodbo’s picture

It looks like the current single-select dropdown JS assumes that the "Ensure that only one result can be displayed" option is enabled in the facet's config, since it only supports functioning as a traditional single select dropdown (one selected option only).

The idea proposed in #25 and #27 would be a really cool extension of the single select dropdown functionality yep (or a different widget altogether). So how it currently works with the "Ensure that only one result can be displayed" disabled, but with support for it in the JS. Something like the first multiselect example on http://hemantnegi.github.io/jquery.sumoselect/sumoselect_demo.html - with the limitation of selection one option at a time, but it would be similar conceptually/visually?

I think having a multiselect widget would still be useful, mostly for people who want to use libraries like Chosen, but given how much juggling it requires to get it to work fully, I'm not sure how much of a priority it should be. (As an aside, it's interesting that to enable Chosen and friends, we are turning a list of links into a select element, and then back into a list of items to create the final widget).

geek-merlin’s picture

Yeah, fully agree. So the new or renamed issue might be "Make select dropdown widget work if facets are not restricted to onl-one-result".

chr.fritsch’s picture

We are working on multiple select dropdown widget support. First, we need an API for other widgets to hook in. That is provided by #3031581: Provide JavaScript API for facet widgets. Then we can use that API to integrate with the select2 widget #3031587: Support for AJAX Facets.

So in order to get that done, we need some manual testing of #3031581: Provide JavaScript API for facet widgets.

yasmeensalah’s picture

Re-rolled the patch to work with version 8.x-1.4.

hanness’s picture

Status: Needs work » Needs review

Thanks @yasmeensalah for re-rolling!

#32 works fine for me with Sumoselect, tested without and with AJAX enabled.

Setting NR to get review of code (I'm not a coder) and the discussion starting at #25. As discussed there: it is still not possible to select multiple facet items before applying the filter.

geek-merlin’s picture

Title: Multiple select dropdown widget » Create a multiple select dropdown widget
Status: Needs review » Postponed (maintainer needs more info)
Parent issue: » #3075378: [META] Overview of Facets + Ajax issues

According to #31, this had been fixed in #3031587: Support for AJAX Facets. Is this correct?

geek-merlin’s picture

pieterjandp’s picture

Nitpicking: the facetsPreviousValue data can be attached to $dropdown outsite of the each loop. The patch works for me combined with select2 (using custom JavaScript, not https://www.drupal.org/project/select2) and patch #6 from #3014027: Hide Default Option for Dropdown Widget.

introfini’s picture

I've tried the patch but only the first selected option is added to the URL.

letrollpoilu’s picture

My goal is to install this patch and this one

I was advice to switch to the development branch to apply it. And now I have an issue applying this patch:

I now have deleted the modules/contrib/facets folder

Then did composer require drupal/facets:1.x-dev

Then git apply -v ../../../../patches/modules/contrib/facets/facets-2811331-24-multiple-dropdown-widget-36.patch

And I had this error:

Checking patch js/dropdown-widget.js...
Hunk #2 succeeded at 91 (offset 15 lines).
Checking patch src/Plugin/facets/widget/DropdownWidget.php...
error: while searching for:
  public function build(FacetInterface $facet) {
    $build = parent::build($facet);
    $build['#attributes']['class'][] = 'js-facets-dropdown-links';
    $build['#attached']['drupalSettings']['facets']['dropdown_widget'][$facet->id()]['facet-default-option-label'] = $this->getConfiguration()['default_option_label'];
    $build['#attached']['library'][] = 'facets/drupal.facets.dropdown-widget';
    $build['#attached']['library'][] = 'facets/drupal.facets.general';

error: patch failed: src/Plugin/facets/widget/DropdownWidget.php:32
error: src/Plugin/facets/widget/DropdownWidget.php: patch does not apply
Checking patch tests/src/Unit/Plugin/widget/DropdownWidgetTest.php...
error: while searching for:
    $this->assertInternalType('array', $output);
    $this->assertCount(4, $output['#items']);

    $this->assertEquals(['js-facets-dropdown-links'], $output['#attributes']['class']);

    $expected_links = [
      $this->buildLinkAssertion('Llama', 'llama', $facet, 10),

error: patch failed: tests/src/Unit/Plugin/widget/DropdownWidgetTest.php:33
error: tests/src/Unit/Plugin/widget/DropdownWidgetTest.php: patch does not apply

The hiding patch applies properly though. What did I do wrong?

capysara’s picture

@letrollpoilu Both patches are modifying the same code, and the error messages gives you some clues about where to look. It might be possible to apply the first patch, then manually apply the second, though I haven't looked to see how complicated that would be. Manually applying the patch would involve looking at the .patch and making the changes directly in the file(s). Since git couldn't do it, it may take some re-work. For troubleshooting, it's probably best to apply and test them individually to be sure they work as expected before you try combining them. And, when you do, be sure to report back in the issue queues.

letrollpoilu’s picture

Thanks a lot for the enlightenment, now I see I didn't do anything wrong :)
I think this will be a bit too much for me to combine those 2 patches.

I could solve the problem of the placeholder by not putting any label and writing a scss rule:

[data-drupal-facet-id="facet_news_tags"]{
    ~ .chosen-container-multi .chosen-choices:not(:focus-within) li:first-of-type.search-field:before{ 
        content: "By tags";
        @include placeholderStyles;
        padding: 0.5rem;
        line-height: 2.3;
    }
}

This works ok for me now. Thanks again for the help.

brunodbo’s picture

Status: Postponed (maintainer needs more info) » Active
Issue tags: +Needs reroll

@geek-merlin re:#34: As far as I can tell, #3031587: Support for AJAX Facets added support specifically for Select2, using the new JS API that was added in #3031581: Provide JavaScript API for facet widgets.

#3031581: Provide JavaScript API for facet widgets added the API, and implemented that API in the dropdown widget, but didn't add a multiselect dropdown (I assume it was out of scope of that issue). So I think we still need this issue, to add generic support for multiselect dropdowns, if this still seems like the right approach given what was added in #3031581: Provide JavaScript API for facet widgets.

The patch in #36 applies to Facets v1.4, but no longer to the latest dev, as mentioned in #38, so it needs a reroll.

spelcheck’s picture

StatusFileSize
new3.66 KB

Re-rolled for 1.x-dev.

spelcheck’s picture

StatusFileSize
new5.49 KB

Rolled for 1.x-dev:
- added logic to not render default option when default_option_label is blank
- added 'disabled' property to default option
- added parent class for options that have children
- added 'level-[depth]' classes for options that are children
- re-added 'facet-inactive' class for testbot

spelcheck’s picture

Apologies for stepping on https://www.drupal.org/project/facets/issues/3014027 in this patch. Intuitively, I felt that by leaving the default option text blank I expected the default option to simply not be rendered (the lightest weight solution no?). That being said, consider how interwoven these basic little improvements are.. there isn't much of a chance of a handful of them ever patching cleanly together but they would naturally all be used together.

I'd be happy to roll this without the default option logic, just say the word (or feel free to roll your own).

spelcheck’s picture

StatusFileSize
new6.3 KB

- added stock 'disableFacet' functionality from checkbox-widget.js for visual feedback, indication of reload in progress.

spelcheck’s picture

Status: Active » Needs review
Issue tags: -Needs reroll
vaccinemedia’s picture

Using the latest patch #45 I'm struggling to get the selects to use chosen or select2 using the chosen module, select2_all and select2boxes.

If I'm using Chosen, I need to place a view anywhere on the page which has an exposed filter in order to render a select on the page. This then loads the chosen library and the facets have this applied. This shows that the facets are not triggering the loading of the Chosen library.

Keeping the test view with exposed select filter on the page - select2_all does not load at all - I'm assuming this module only applies select2 on the admin pages.

Using select2boxes the facet selects (either single OR multiple selects) do not have select2 applied - the views exposed filter does have it applied.

neclimdul’s picture

StatusFileSize
new3.55 KB
new6.18 KB

Reroll

  1. +++ b/js/dropdown-widget.js
    @@ -40,17 +40,23 @@
    +        .prop("disabled", true)
    

    I replaced this with single quotes to match file code style.

  2. +++ b/js/dropdown-widget.js
    @@ -69,24 +75,66 @@
    -        var anchor = $($ul).find("[data-drupal-facet-item-id='" + $(this).find(':selected').data('drupalFacetItemId') + "']");
    +        // var anchor = $($ul).find("[data-drupal-facet-item-id='" + $(this).find(':selected').data('drupalFacetItemId') + "']");
    

    Removed this line/comment entirely.

Also, did a clean reroll of 36/42 before the default changes and made an interdiff to make the changes easier to review. Attached as well.

claudiu.cristea’s picture

Status: Needs review » Needs work
Issue tags: +Accessibility

With this patch, indeed, I can see the select as a multiselect. The problem is that is not following the standard multiselect user interaction and the selections are accumulated. When I click an option, without holding CTRL/⌘, I'm expecting that the old selection is replaced by the new one. However, the new selection is added to the old one even I don't keep CTRL/⌘ pressed. New options should be appended to existing ones only when CTRL/⌘ is pressed.

However, the opposite works. I can deselect by holding CTRL/⌘ and click.

Also there is an accessibility issues here: You cannot do selections using only the keyboard. As soon as the select receives the focus and you move with up/down arrow keys, the Ajax request is submitted. But it shouldn't be that way. The server round trip should not be triggered on up/down arrow but on selecting with space. And, again, multiselect with CTRL/⌘ and/or SHIFT should work like on any other multi-select

thomaswalther’s picture

Thanks to #49.
Please improve new ui elements like the native html form elements with the same short key support.

nuuou’s picture

StatusFileSize
new6.2 KB
new11.58 KB

Balancing Facets patches is becoming tricky for sure!

I've attached two patches:
1. A re-roll against 2.0.x (at the time of this, 2.0.1 just released).
2. A re-roll + combined patch from a Views AJAX History patch my team is using (https://www.drupal.org/node/3106111)

Hopefully others find it useful too.

mkalkbrenner’s picture

Version: 8.x-1.x-dev » 2.0.x-dev
Status: Needs work » Needs review
spelcheck’s picture

       var $default_option = $('<option></option>')
+        .prop('disabled', true)
         .attr('value', '')
         .text(default_option_label);

@nuuou .prop('disabled', true) is missing in the building of the default option. Was it intended to be removed from this roll of the patch?

Thank you for tackling re-rolling this, it's much appreciated!

spelcheck’s picture

StatusFileSize
new6.23 KB

I'm needing the disabled property on default_option element for an existing project, so posting a patch that re-includes it. If I hear that the removal had something to do with accessibility, I'll hide this patch so we can address it in the future.

carolpettirossi’s picture

Status: Needs review » Needs work

I could not apply #51 or #54 to 2.0.1 nor 2.0.2

capysara’s picture

It looks like dev and 2.0.2 were released on the same day, so the patch may need to be re-rolled regardless, but generally patches should be created and applied based on the dev version.

nuuou’s picture

Late to this!

@spelcheck: I didn't remove that intentionally, so likely just a miss on my part when I re-rolled that patch. Thanks for pointing that out!

@carolpettirossi: This was created against 2.0.x at the time, and I just verified I'm able to apply both patch #51 (first one) and #54 successfully (both on Facets 2.0.1 and 2.0.2)

Do you have any other patches applied that might be conflicting?
If you have any other Facets patches applied, those could be conflicting or failing, so check those first. You might need to roll your own patch for combined patches if so.
If not and this is the only patch you have for Facets and still having issues, could you provide more info about where the patch is failing?

geek-merlin’s picture

vasyok’s picture

Hello drupalers!

I apply patch #54, but i see no changes in faset's dropdown.

What options should be selected in facet settings?

david.muffley’s picture

StatusFileSize
new6.23 KB

Rerolled for 2.0.6. Interdiff is failing; added `once` argument to the function for dropdown-widget.js.

vensires made their first commit to this issue’s fork.

vensires’s picture

Status: Needs work » Needs review
vensires’s picture

I have applied changes from #60 into the new MR.

Also uploading patch for anyone who wants it.

vselivanov’s picture

Changed patch #64 to be applied with Facets 3.0 - 3.0.x (d9af3451 commit as of Jan, 31).
In case someone uses Facets 3.0 with blocks.

vselivanov’s picture

Updated the patch #65 to match the latest Facets 3.0.3 release from 24 Apr 2026.