Choices: searchFloor and search text filter interaction

Created on 31 Mar 2017  路  7Comments  路  Source: Choices-js/Choices

I've recently started a new project with Choices (latest version), and I'm noticing a strange behaviour in filtering.

With a near-default setup:

image

I'm getting these two sets of behaviour on standard single-choice select boxes:

image

image

I managed to narrow it down to the minimum character - based on the above two outcomes (and the fact that other random strings such as zz don't show any results), it appears to only be searching on the characters above the minimum search length (i.e. + and a)

question

Most helpful comment

@lewishowles Choices uses fuse, a fuzzy-matching string search which allows for typos. By default, the fuzziness is very lenient, which can lead to confusing results. It sounds like what you're looking for is exact string matching.

If you're looking for exact matching from the beginning of the string, instruct fuse to accept only exact matches by giving it a fuzziness threshold of 0:

var choices = new Choices('.form__select', {
    shouldSort : false,
    fuseOptions: {
        threshold: 0
    }
});

If instead you're looking for exact matching but from anywhere in the string, AFAIK fuse doesn't support this directly but you can hack it. Fuse calculates the fuziness of a result as a function of correctness and distance (i.e. offset), so you can tell it to accept a low fuziness threshold and give it a high distance parameter, which causes distance to be weighted very lightly:

var choices = new Choices('.form__select', {
    shouldSort : false,
    fuseOptions: {
        threshold: 0.1,
        distance: 1000
    }
});

Note that if your fields are very long, you may have to tweak the above parameters somewhat.

All 7 comments

Hi @lewishowles,

Could you send me the HTML for '.form__select' as well as your Choices config please?

Thanks

Hi Josh,

The above is the only config, so:

var choices = new Choices('.form__select', {
    shouldSort : false
});

The select field in question is:

<select id="ddlBedrooms" class="form__select" name="ddlBedrooms">
    <option value="0">Any Beds</option>
    <option value="1">1+ Bedroom</option>
    <option value="2">2+ Bedrooms</option>
    <option value="3">3+ Bedrooms</option>
    <option value="4">4+ Bedrooms</option>
    <option value="5">5+ Bedrooms</option>
</select>

By default Choices will filter on both the value and the label of each choice with a default search floor of 1. This means your choices will only filter after a user has inputted a second character (but will search using the entire value).

As your labels already include the value, I would set your config to this:

var choices = new Choices('.form__select', {
  shouldSort: false,
  sortFields: ['label']
});

I've realised that sortFields is a confusing name! It should be searchFields - I'll update this soon.

Let me know if this solves your problem, thanks.

I don't think that's quite the issue - it's matching all fields whose label contains a + when I type 5+ or any single character followed by a +.

e.g.

  • 1+
  • 2+
  • Q+
  • %+
  • 拢+

All match five of the six possible options, when only the first two should match anything at all, and those two should only match one value - not five.

Fiddle at https://jsfiddle.net/lewishowles/tfbryzgx/ using the default JS, default CSS and the config and select above.

Note that you can type any single character followed by a plus and get five results. You can even type 5+, 55+, 555+ and 5555+ and they will all match 5+ Bedrooms (though 55555+ won't)

@lewishowles Choices uses fuse, a fuzzy-matching string search which allows for typos. By default, the fuzziness is very lenient, which can lead to confusing results. It sounds like what you're looking for is exact string matching.

If you're looking for exact matching from the beginning of the string, instruct fuse to accept only exact matches by giving it a fuzziness threshold of 0:

var choices = new Choices('.form__select', {
    shouldSort : false,
    fuseOptions: {
        threshold: 0
    }
});

If instead you're looking for exact matching but from anywhere in the string, AFAIK fuse doesn't support this directly but you can hack it. Fuse calculates the fuziness of a result as a function of correctness and distance (i.e. offset), so you can tell it to accept a low fuziness threshold and give it a high distance parameter, which causes distance to be weighted very lightly:

var choices = new Choices('.form__select', {
    shouldSort : false,
    fuseOptions: {
        threshold: 0.1,
        distance: 1000
    }
});

Note that if your fields are very long, you may have to tweak the above parameters somewhat.

Hmm, saying 5555+ == 5+ is confusing is probably very lenient.

Thanks for the explanation, but I ended up ditching Choices so can't test.

The solution from https://github.com/jshjohnson/Choices/issues/135#issuecomment-302124496 works. Thanks. Would be good to have this as an example.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zslabs picture zslabs  路  6Comments

rstacruz picture rstacruz  路  4Comments

ckotzbauer picture ckotzbauer  路  5Comments

ckotzbauer picture ckotzbauer  路  5Comments

sebastien-roch picture sebastien-roch  路  3Comments