I'd like to have some disabled options. Anyone know how I could add that functionality?
I could use suggestion objects with a disabled property. However, I'll need a way of attaching a special css class to each disabled item. Also, I'll need to prevent the default behaviour on focus for disabled items.
A "section name" acts just like a disabled item should: a css class is attached so it can be styled grey, and it doesn't respond to mouse/keyboard events. It's a shame that it couldn't be a more generic feature that could extend to any kind of disabled item, and we could attach different css classes to differentiate each type.
I was able to use the section name functionality as a way to disable options with one change to the code: Line 524 of Autosuggest.js becomes:
//return section.suggestions.length === 0 ? null : (
return section.suggestions.length === 0 ? sectionName : (
Then my getSuggestions() function before filtering looks something like this:
getSuggestions(input, callback) {
const options = [
{name: 'apple', count: 1},
{name: 'mango', count: 0},
{name: 'orange', count: 3},
{name: 'banana', count: 2},
{name: 'madsyfruit', count: 6}
];
let results = [];
options.forEach((option) => {
let obj = (option.count) ?
{sectionName: null, suggestions: [option.name]} :
{sectionName: option.name, suggestions: []};
results.push(obj);
});
return callback(null, results);
}
So it's an ugly hack and I can't use sections with it, but it seems to work.
@approots Please see this discussion about disabled suggestions. I'm still waiting to see a convincing use case for having disabled suggestions in an autosuggest component. Could you share your use case please?
My use case is a job category search. We have thousands of job categories organized by popularity. However, even the most popular job category may not always have jobs on offer. For a given search input, we want to show the first x number of the most popular job categories. For example, a user types "desi", and we may show "web designer" and "print designer". However, if there are no jobs presently offered under "print designer", we need to disable that item because there is no associated content.
In other words, we'd like the user to potentially see all our categories (so that they know what types of jobs we offer), but only be able to select a category containing actual content.
Regardless of use case though, I think the react-autosuggest could be more flexible and easier-to-use with this change:
this:
[{
suggestions: [<suggestion>, <suggestion>] // This section won't have a title
}, {
sectionName: 'Second section',
suggestions: [<suggestion>, <suggestion>, <suggestion>]
}]
becomes:
[
{suggestion: 'fruit', className: 'category', disabled:true},
{suggestion: 'apple'},
{suggestion: 'mango', className: 'outofstock', disabled:true},
]
So, I seem to have the disabled options working:
Autosuggest.js
sectionIterator.js
Not too hard thanks to your design. Most changes were made in sectionIterator.js. Instead of passing in a number representing the number of suggestions (or an array of numbers for multiple sections), I pass in an array of indexes corresponding to all active suggestions (or an array of arrays of indexes for multiple sections).
@approots I'm glad you found a way to implement disabled suggestions. If you could post a link to the website you are working on, that would be great. I'd be interested to see the end result.
Looks like at this point there is not enough interest from the community to implement disabled options in react-autosuggest. As a maintainer, sometimes I need to make hard calls and decide not to implement a particular feature request. Sorry.
A +1 for this feature. Our usecase is an autosuggest for a contact list for sending email where some contacts may have unsubscribed themselves.
Optimally we could show them there as disabled since; 1. Not showing them at all might confuse the user since he's looking for a specific contact he expects to be in the list and 2. Letting them select an unsubscribed user and then not sending the email would also be confusing.
@dbackeus That makes sense. react-autosuggest uses react-autowhatever as its rendering layer. Feel free to submit a PR in react-autowhatever to support disabled items.
I need this feature as well. My usecase is I have form of creating/editing a "Site Group" that has the auto suggest field for the sites. Requirement is to show the site, which is already added in the group, in the suggestion area but disabled to avoid duplicates and give the user feeling that its already in the group.
I don't want to use approots's solution.
Another +1. I now have a use case where we want users to see that an option exists, but they don't have permission to use it at the moment because of reasons that they will understand when they see it.
Instead of filtering out those results, this prevent would our users from thinking that an option doesn't exist, and going to the list where the options are drawn from, and creating a new item for that list. As it stands right now, we have to hide the options they aren't able to use, which has caused duplicates to be made.
This would be trivial if parent selectors or :has() were a thing in CSS, as you could set a class in renderSuggestion, and then apply the disabled CSS to its parent.
.suggestionsContainer
position absolute
width 100%
...etc
li:has(>div[class='disabled'])
opacity 0.6
cursor default
pointer-events none
Actually I _just_ figured out how to accomplish this with CSS (the exact CSS is particular to my setup, but hopefully this gives the general idea):
.suggestionsContainer
position absolute
width 100%
etc...
li
cursor default
pointer-events none
> div[class*='disabled']
opacity 0.6
> div:not([class*='disabled'])
margin -0.7em
padding 0.7em
cursor pointer
pointer-events all
.suggestion
cursor pointer
padding 0.7em
...
Basically, disable all mouse events for list items in the suggestionsContainer, and re-enable them (as well as fixing the padding/margins for the cursor) if there _isn't_ a "disabled" class associated with the item.
In terms of handling the keyboard input, I simply ignore method=enter in onChange, and do nothing in onSuggestionSelected if the incoming suggestion has a "disabled" flag set.
It's not perfect, but it accomplishes disabling options, while still allowing them to be seen.
+1 from me. Use case - we have nested structure and components can be at different hierarchical levels. First level is not clickable but we want to display it to make structure easier to reason about.
+1 from me.
You can treat "disabled" items as "separators". Just think of a very simple task - how to add a horizontal line at a certain place in the list? Currently the only way is to break the list into 2 sections but it looks too tricky and dirty for such simple task.
Actually the only thing you need to implement this feature is allow disabling of mouse and keyboard events for exact items. Styling is not a problem because there is enough flexibility to do it.
You can draw a separator with CSS only. That is, if you know where you want to insert a separator in renderSuggestion, you only add something like "border-bottom: 1px solid black" (or border-top) over the div tag which contains the suggestion.
Most helpful comment
Actually I _just_ figured out how to accomplish this with CSS (the exact CSS is particular to my setup, but hopefully this gives the general idea):
Basically, disable all mouse events for list items in the
suggestionsContainer, and re-enable them (as well as fixing the padding/margins for the cursor) if there _isn't_ a "disabled" class associated with the item.In terms of handling the keyboard input, I simply ignore
method=enterinonChange, and do nothing inonSuggestionSelectedif the incoming suggestion has a "disabled" flag set.It's not perfect, but it accomplishes disabling options, while still allowing them to be seen.