How can I disable automatic filtering in selectize.js? Built-in / plugin / modilfy source?
Asked Answered
A

5

5

I have a selectize.js drop-down, which loads a list of items from the server using ajax. The server provides an autocomplete from the given string, so I don't need selectize's native filtering. Besides, I really need to turn it off: The server output may be totally different from selectize's one.

The data is fed into JavaScript objects fine, but selectize doesn't even show a popup, since those items doesn't match selectize's filter. How can I disable or modify native filtering and the matches highlighting algorithm? Either with a built-in option, or with a plugin? Or is the only way to go to modify the source?

EDIT:

searchField: false / function() doesn't work (and documentation doesn't mention them as available option values)

EDIT2:

Eventually came up with this trick: Add a fake field to each item, assign a search string to it and tell selectize to use is as a searchField. But obviously, there should a better way, so the question is still open.

Arne answered 3/9, 2015 at 14:50 Comment(0)
E
2

I needed to disable searching so iPhones won't be displaying the keyboard. The solution I settled on makes the search field readonly by hooking into the selectize setup (without modifying the actual source, so selectize is still updatable). Here's the code, if anybody needs it:

// Put this code after you've included Selectize
// but before any selectize fields are initialized
var prevSetup = Selectize.prototype.setup;

Selectize.prototype.setup = function () {
    prevSetup.call(this);

    // This property is set in native setup
    // Unless the source code changes, it should
    // work with any version
    this.$control_input.prop('readonly', true);
};
Ephemeris answered 15/9, 2016 at 8:34 Comment(1)
This is a clean solution, the best way to implement custom behaviour on 3rd party lib, so accepting itArne
D
10

I use this solution (if results from server is ordered correctly):

    score: function() { return function() { return 1; }; },

or this (if need order)

    score: function(search) {
        var score = this.getScoreFunction(search);
        return function(item) {
            return 1 + score(item);
        };
    },

Sifter uses the score function to filter. Result of score must be > 0.

Distract answered 10/3, 2016 at 15:4 Comment(2)
This is a much cleaner, safer and more future-proof solution. I just want to add that if the Selectize control is hooked up to a back-end search that returns ranked results (e.g. Elastic Search), then this code can be changed to return the rank field instead of the internally generated score: score: function() { return function(item) { return item.rank; } }Brannan
This is the best way. But I had a problem with it. Using this code made my field add new results (from ajax) to the items list and not remove old ones! (any thing I was searching, the results got growing). I had to refresh the results manually on load function: load: function (query, callback) { this.clearCache('option'); this.clearOptions(); this.refreshOptions(true); ...Villein
G
3

I solved with onInitialize method in selectize parameters:

$("select").selectize({
        onInitialize: function() {
             this.$control_input.attr('readonly', true);
        }
});
Guyguyana answered 14/9, 2020 at 4:7 Comment(0)
A
2

So, searching the code, I've found out, that Sifter module (searching/sorting engine, which Selectize relies on), it does have an option to disable filtering, we just need to forward it up, to Selectize. I can suggest the following patch:

Locate the function getSearchOptions() in Selectize main .js file:

https://github.com/brianreavis/selectize.js/blob/master/dist/js/selectize.js

Here is the before:

getSearchOptions: function () {
    var settings = this.settings;
    var sort = settings.sortField;
    if (typeof sort === 'string') {
        sort = [{field: sort}];
    }

    return {
        fields:      settings.searchField,
        conjunction: settings.searchConjunction,
        sort:        sort
    };
}

And here's the after: (added a comma, 5 lines of comments, and the patch itself)

...
getSearchOptions: function () {
    var settings = this.settings;
    var sort = settings.sortField;
    if (typeof sort === 'string') {
        sort = [{field: sort}];
    }

    return {
        fields:      settings.searchField,
        conjunction: settings.searchConjunction,
        sort:        sort,
        // A patch to allow to disable native filtering, in the case,
        // when we want to provide search results on the server side.
        // Negative form of the setting is to avoid changing the standard
        // behaviour, (and, possibly, ruining the existing code), when this
        // parameter is missing.
        filter      : !settings.dontFilter
    };
},
...

Sorry, I just don't have time to create a branch on Github, the project deadline is near, and also, actually not sure, that I'll manage to be a fine contributor for now, due to some lack of experience working in Github. So, just posting a quick workaround.

Arne answered 6/9, 2015 at 16:1 Comment(2)
With brief testing, with this approach, as one changes the search string, "old" options from previous remote loads are not removed. E.g. if one types "foobar" slowly, causing remote searches "foo" and "foobar", the items returned with "foo" remote search are also shown after "foobar" remote search is returned and update to the component.Thorndike
Just do in load method: delete self.loadedSearches[query]; $.each(self.options, function(k, v) { delete self.options[k]; delete self.sifter.items[k]; });Surcease
E
2

I needed to disable searching so iPhones won't be displaying the keyboard. The solution I settled on makes the search field readonly by hooking into the selectize setup (without modifying the actual source, so selectize is still updatable). Here's the code, if anybody needs it:

// Put this code after you've included Selectize
// but before any selectize fields are initialized
var prevSetup = Selectize.prototype.setup;

Selectize.prototype.setup = function () {
    prevSetup.call(this);

    // This property is set in native setup
    // Unless the source code changes, it should
    // work with any version
    this.$control_input.prop('readonly', true);
};
Ephemeris answered 15/9, 2016 at 8:34 Comment(1)
This is a clean solution, the best way to implement custom behaviour on 3rd party lib, so accepting itArne
F
0

With a little bit of CSS and a little bit of JS we can create this. And it looks perfect.

var select = $("#my-select-input");
$(select).next().find("div.selectize-input").addClass("no-searchable"); // Adding style to the div
$(select).next().find("div.selectize-input > input").addClass("no-searchable"); // Adding style to the input
$(select).next().find("div.selectize-input > input").prop("readonly", true); // Setting the input to read-only
$(select).next().find("div.selectize-input > input").prop("inputmode", "none"); // Guarantee in case it opens on the cell phone and click on the input no keyboard is opened
$(select).next().find("div.selectize-input > input").focus(function () { // Hack for when the search input gets the focus it will automatically blur.
    $(this).blur();
});
.no-searchable {
    cursor: pointer !important;
    background-color: #FFFFFF !important;
}
.has-items input.no-searchable {
    width: 1px !important;
}
Fatshan answered 25/3, 2021 at 0:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.