Set display value to empty when open - HeadlessUI Combobox - reactjs

I'm new to React. I got a question regarding Combobox of HeadlessUI.
How do we set the value to empty when combobox is open? I'm trying to follow this autocomplete pattern below. When the options are opened, the input value is set to empty, so user can type straight away.
This is from existing example of Combobox, see that the input value is not empty when options are opened
What I have tried so far is to checking the open state of combobox inside displayValue, but it didn't work. The open is definitely not matched with the current open state. I believe because the function store the previous value of open.
<Combobox.Input
displayValue={(person) => {
console.log("open", open);
if (open) {
return "";
}
return person.name;
}}
onChange={(event) => setQuery(event.target.value)}
/>
Here is my CodeSandbox.
I noticed we have two render props for Combobox.Input which are open and disabled. How to use that prop?
Thank you

Try to add key props to your Combobox.Input, it should work
<Combobox.Input
key={open}
displayValue={(person) => {
if (open) {
return "";
}
return person.name;
}}
onChange={(event) => setQuery(event.target.value)}
/>

Related

unable to edit pre populated textboxes using react

I have a form that has textboxes that are prepopulated from an WebAPI. When I try to delete the text in the textbox to make a change it doesn't delete the prepopulate text. If I try to type over the text, I can see only the first letter of the word I'm typing in the console, but nothing changes on the UI: It' like the textbox is in readonly mode WHICH IT IS NOT
const Details = () => {
const [ server, setServer] = useState([]);
useEffect(() = > {
getServerNames();
}
const getServerName = async() => {
//gets the list of server and their details from the API
}
const serverNameChange = (e) => {
setServer(e.target.value);
}
return (
<div>
{ details.map((data) => {
<input type="text" name="server" onChange={serverNameChange} value={data.serverName} />
))}
</div>
)
};
What am I missing to allow the users to edit the textbox? The textbox is prepopulated with data, however, it can be changed. This is only happening on textboxes that are prepopulated. I don't want to click an Edit button, I want to give the user the ability to make a change in the textbox and then save it.
That might be due to the fact, that data.serverName never changes. It’s basically a static value. If you set the value of an Input, you have to handle the changes (when typing) in the onchange event.
From what I assume, according to your code is that you have multiple input boxes with preloaded values in them and you want to change your serverName if one of them get changed by the value that is in the textinput.
If so, map your details into a state variable:
const [serverNames, setServerNames] = useState(details.map( data => data.serverName));
Map the inputs from your state variable like so:
{serverNames.map((name,index) => {
< input type="text" name="server" onChange={(e) => {updateServerState(e, index)}} value={serverNames[index]} />
}
}
And your updateServerState method looks like that:
updateServerState(e, index) {
let myStateData = [...serverNames];
myStateData[index] = e.target.value;
setServerNames(myStateData);
setServer(e.target.value);
}
Caution: I haven‘t tested the code, just wrote it down. But that should give you an idea of how to solve your issue.
TL;DR; Never use non-state variables for a dynamic value.

check a checkbox when another checkbox is checked in react

I have three checkboxes, when one check box is checked, I want the second check box to be checked automatically. The below code is written in a modal. It will only set the state value, but the checkbox is not getting checked. The change will be reflected only when we close and open the modal again.
<Checkbox className="checkbox-wrapper" onChange={(e, data) => {
if(data.checked){
setAddAccessCheck( ...addAccessCheck,ga.groupId])
setEditAccessCheck([...editAccessCheck,ga.groupId])
}
else{
setAddAccessCheck(addAccessCheck.filter((add) => add !== ga.groupId))
setEditAccessCheck(editAccessCheck.filter((del) => del !== ga.groupId))
}
}}
value={addAccessCheck}
defaultChecked={addSubmitAccessCheck.includes(ga.groupId) ? true : false}
/>```

React-select onChange trigger when user select same option

The onChange of a react-select drop down is getting triggered when I select an already selected value in the drop down. Is there a way to configure react-select to not trigger onChange event if already selected value is selected again.
handleOnChange(value) {
console.log("test");
this.setState({ multiValue: value });
}
render() {
return (
<div>
<Select.Creatable
options={this.state.options}
onChange={this.handleOnChange.bind(this)}
value={this.state.multiValue}
showNewOptionAtTop={false}
/>
</div>
);
}
As you can see the console log calling even if the value is the same. Codesandbox
You can control the value on onChange of react select.
I changed your onChange function with arrow function:
onChange={value => {
if (value !== this.state.multiValue){
this.handleOnChange(value);
}
}}
codesandbox
I'm not sure whether you can disable the change event but as a workaround You can simply hold the current value of the selected item and return from the change handler if the selected item was the previous one like #ahmetkilinc answer, also menu items have an option
isDisabled
that you can change to true when one item is selected, therefore it can't be selected anymore.

How can I disable checkbox for multi value selection in react-dropdown-tree-select?

I am new to React and I stumbled upon react-dropdown-tree-select for a specific need I had allowing users to view data in Tree format for selection in DropDown. But, I want the users to only select 1 value at a time. How can i enforce that?
There is no such property available directly in react-dropdown-tree-select. But you can listen to onChange event and reset the entire data which you have passed in data props with the updated data with only one node selected.
Check the following code.
onChange = (currentNode) => {
// keep reference of default data structure.
const updatedData = this.props.defaultData;
// find node related to currentData in your tree and set checked property
this.setState({data : updatedData });
}
render = () => {
return (
<DropdownTreeSelect
data={this.state.data}
onChange={this.onChange}
/>
);
}
This will basically stop the user from selecting multiple options instead of disabling remainig item you are unselecting the previously selected items.
If you just want one element selected at a time you can use mode="radioSelect"

Control Focus of Multiple FormControl Fields

I have a mapped list of input fields:
<FormControl
name={row_index}
value={barcode.barcode}
placeholder="Barcode - then Enter"
onChange={this.onChange}
onKeyPress={this._handleKeyPress}
disabled={barcode.submitted}
/>
I am currently using onKeyPress to handle submit:
_handleKeyPress = (e) => {
if (e.key === 'Enter') {
const name = e.target.name;
const barcodes = this.state.barcodes;
const this_barcode = barcodes[name];
let apiFormatted = {"barcode": this_barcode.barcode, "uid": this.props.currentSession}
this.postBarcodeAPI(apiFormatted, name)
}
}
I am attempting to focus on the next input field after the current one is successfully submitted. React documentation has an example for manually setting focus on a single input field using ref={(input) => { this.textInput = input; }} />. I have tried using this[‘textInput’+‘1’].focus() (using computed property names, but am getting an error that function is invalid.
EDIT
Per Chase's answer, I am linking to the autofocus documentation, although it doesn't work in this case.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/autofocus
My working solution:
const focusing = index === lastSubmittedIndex + 1 ? true : false;
const refText = focusing || index === 0 ? input => input && input.focus() : null;
<FormControl
name={row_index}
value={barcode.barcode}
placeholder="Barcode - then Enter"
onChange={this.onChange}
onKeyPress={this._handleKeyPress}
disabled={barcode.submitted || barcode.apiCalling}
inputRef={refText}
/>
What I corrected in my code:
1) I am supposed to use inputRef instead of ref for Bootstrap's FormControl component, see here.
2) I am using ilya-semenov's very neat code.
Update
I have other buttons on the page, when user presses them and is at bottom of page, page jumps up to top. Not sure why.
Unless you've set a ref with the key textInput1 then this won't work. Another suggestion would be to move all of the inputs into a separate component and then you can use this.props.children to traverse all your inputs and grab the input at whatever position you want.
EDIT:
You can also use the autoFocus prop to determine if an input should be focused or not.

Resources