Semantic UI dropdown not setting value after selecting option - reactjs

I am using React semantic ui. I am rendering a dropdown in Fieldset. I have written code such that, once a option is selected, the options is updated such that the selected option is removed from the list. But when I select an option from the dropdown, the selected value is not displayed, rather it shows empty.
Here is my code:
This is my dropdown code:
<Dropdown
name={`rows.${index}.mainField`}
className={"dropdown fieldDropdown"}
widths={2}
placeholder="Field"
fluid
selection
options={mainFieldOptions}
value={row.mainField}
onChange={(e, { value }) => {
setFieldValue(`rows.${index}.mainField`, value)
updateDropDownOptions(value)
}
}
/>
My options:
let mainField = [
{ key: "org", text: "org", value: "org" },
{ key: "role", text: "role", value: "role" },
{ key: "emailId", text: "emailId", value: "emailId" },
]
Also, I have:
const [mainFieldOptions, setMainFieldOptions] = useState(mainField)
And,
const updateDropDownOptions = (value:any) => {
let updatedOptions: { key: string; text: string; value: string }[] = []
mainFieldOptions.forEach(option => {
if(option.key != value){
updatedOptions.push({ key:option.key , text:option.key, value:option.key })
}
})
setMainFieldOptions(updatedOptions)
console.log("mainfield", mainField)
}
In onChange, if I dont call updateDropDownOptions() method, the dropdown value is set. But when I call the method, its giving blank value. Please help.

There are few changes required in your code,
You are pushing the entire initialValues when you are adding a row which is an [{}] but you need to push only {} so change your code to initialValues[0] in your push method.
Its not needed to maintain a additional state for the options. You can filter the options based on the selected option in other rows which is available in the values.rows .
Util for filtering the options
const getMainFieldOptions = (rows, index) => {
const selectedOptions = rows.filter((row, rowIndex) => rowIndex !== index);
const filteredOptions = mainField.filter(mainFieldOption => !selectedOptions.find(selectedOption => mainFieldOption.value === selectedOption.mainField));
return filteredOptions;
}
Call this util when rendering each row
values.rows.length > 0 &&
values.rows.map((row, index) => {
const mainFieldOptions = getMainFieldOptions(values.rows, index);
Working Sandbox

Related

DropDownPicker worked after clicking second time only

I have two dropdown picker. One is dependent on another one. If I click color on one dropdown another dropdown should show list of colors but its not working properly. If I click on first dropdown first time and select color second dropdown shows nothing but when I click on color again it shows the result in second dropdown.
Not sure why its happening
Here is my slack link:
https://snack.expo.dev/#anamika1593/carlist
I fixed your code. Your problem was that you set the state in function and then you used the variable from the state "selected" but when you set the state. The Variable doesn't change immediately and you used "old value" from the state.
if (item.label === "Color") {
const colorData = [...new Set(data.map((val) => val.car_color))];
var color = colorData.map(function (val, index) {
return {
id: index,
value: val,
label: val,
};
});
return setChildValue(color)
} else if (item.label === "Model") {
const modelData = [...new Set(data.map((val) => val.car_model))];
var model = modelData.map(function (val, index) {
return {
id: index,
value: val,
label: val,
};
});
return setChildValue(model)
} else if (item.label === "Year") {
const yearData = [...new Set(data.map((val) => val.car_model_year))];
var year = yearData.map(function (val, index) {
return {
id: index,
value: val,
label: val,
};
});
return setChildValue(year)
}
You have to do it like this and use item that you put in the function.
Fixed code

Material UI Autocomplete Dropdown option not working after switching tabs

In my new project, I am using material UI autocomplete within tabs, and using useImmer hooks for state management. Values in the autocomplete are populated through map function and everything works properly. However, the dropdown functionality is not working after switching the Tabs.
The values are reaching to this component as
const Dropdownlist = ({ defaultRates, value, onChange, index }) => {
return (
<Autocomplete
{...defaultRates}
size="small"
inputValue={value}
value={value}
autoSelect={true}
clearOnEscape={true}
onChange={(event, newValue) => {
onChange( newValue, index );
}}
renderInput={(params) => <TextField {...params} />}
/>
);
};
export default Dropdownlist;
Values of 'defaultRates' was built using
const ratings =
Rates.map((charge) => {
return ({ id: charge.rateid, label: charge.rate });
});
const defaultRates = {
options: ratings,
getOptionLabel: (option) => option.label,
};
Then,
const Rates = [
{
rateid: 101,
rate:"10"
},
{
rateid: 102,
rate:"30"
},
{
rateid: 103,
rate:"1"
},
{
rateid: 104,
rate:"2"
},
];
export default Rates;
Finally, On Change functionality
const onChange = (e,i) => {
let newState;
if(e)
{
const { id, label } = e;
newState = transactions.map((item, index) => {
var tds = (label/100)*item.amount;
if (index === i) {
return {
id: item.id,
transaction: item.transaction,
amount: item.amount,
name: item.name,
type: item.type,
ts:item.ts,
tr:label,
tds: tds,
error:false,
};
} else {
return item;
}
});
setTransactions(newState);
}
}
In the first tab I have many autocomplete dropdown and the selected values are also using in the second tab. If I switch to Tab2 and return back to Tab1, I can see the selected values there. But If I want to change the selected value, nothing happens while clicking the dropdown icon. Please let me know if anyone ever experienced in this context. Would like to know if I using Material UI autocomplete parameters in the right way?
I have gone through Material UI documentation and Autocomplete params. Please advise if it is a state management issue or Mat UI bug?

Update nested React state?

I'm trying to update part of a state object that is nested. This is the object:
const [buttonObject, setButtonObject] = useState({
intro: [
{
id: '123',
name: 'first_intro_name',
selected: false,
},
{
id: '124',
name: 'second_intro_name',
selected: false,
},
],
experience: [
{
id: '789',
name: 'first_experience_name',
selected: false,
},
{
id: '8910',
name: 'second_experience_name',
selected: false,
},
],
});
When a button is clicked I want to toggle the selected state. I'm using a click handler that looks like this:
const handleButtonClick = ({ id, selected }) => {
if (id === '123') {
buttonsObject.intro.map(
pref => (pref.selected = pref.id === id ? !pref.selected : selected)
);
setButtonsObject(buttonsObject);
} else if (id === '124') {
buttonsObject.intro.map(
pref => (pref.selected = pref.id === id ? !pref.selected : selected)
);
setButtonsObject(buttonsObject);
}
};
It would handle experiences as well. The issue is that right now it seems like rather than updating the object it just overwrites the object or creates a new one. It also doesnt pass that information back down to the component even though I have it routed correctly so it should.
Is there better/correct syntax for updating nested state like this?
Thanks.
instead of checking again with if condition use higher order array function and spread operator to get optimal solution.
setButtonObject(previous => {
return {
...previous,
info: previous.info.map(item => item.id === id ? {
...item,
selected: true
} ? item)
}
})

React-Select on selecting a value the dropdown options unavailable

Process the prop from another component to match in the react-select options
const labelOptionsProcessed = []
labelOptions.map(item => {
let tmpObj = {
id: item.id,
label: item.name,
name: item.name
}
labelOptionsProcessed.push(tmpObj)
})
tmpObj is the structure of the options
<Select
options={labelOptionsProcessed}
isMulti
></Select>
When a select a dropdown value , the options change to no data available
Before selecting an Option :
After Selecting an Option:
StackBlitz: https://stackblitz.com/edit/react-4ddnq7
You have to set a value property for options instead of id
EX:
const labelOptionsProcessed = []
labelOptions.map(item => {
let tmpObj = {
value: item.id, // here
label: item.name,
name: item.name
}
labelOptionsProcessed.push(tmpObj)
});
I guess this is not the proper way to generate the options list, I'd do something like this
const labelOptionsProcessed = labelOptions.map(({ value, name: label, name }) => {
return {
value,
label,
name
};
});

React Selecting dropdown option multiple times

I am wanting to be able to select a language I have called "Skip" more than one time without it disappearing from the dropdown. Currently, any language I select will disappear from the dropdown. Is this possible? Here's my code:
const languages = [
{ key: 'skip', text: 'Skip', value: 'Skip' },
{ key: 'english', text: 'English', value: 'English' },
{ key: 'french', text: 'French', value: 'French' },
]
handleAudioInputChange = (e, { name, value }) => this.setState( { [name]: value })
<Form.Select fluid search label='Audio Channels' name='audiochannelsValue' value={audiochannelsValue} options={languages} placeholder='Choose Audio Channels' onChange={this.handleAudioInputChange} multiple = "true"/>
I've tried multiple things such as hideSelectedOptions = {false}, but this does not seem to work. Any ideas?
If you only want a string based on the user input, you could do:
handleAudioInputChange = (e, { value }) => {
this.setState(prevState => {
const newVal = `${prevState.audiochannelsValue.length ? '/' : ''}${value}`;
return {
textValue: prevState.textValue.concat(newVal),
audiochannelsValue: value
};
});
}
This will build a string based on the previous state and separate each value with /. Haven't tested it, but it should generate (in order):
English
English/Skip
English/Skip/French
English/Skip/French/Skip

Resources