Material UI Autocomplete Dropdown option not working after switching tabs - reactjs

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?

Related

react-select not updating value when changing option

I load my supplier using SWR. But it is wrapped in various classes. I get it like so:
const supplier = new Supplier(supplierID)
This gives me a supplier object.
I then have a select drop down:
options = assetPriceCategories.map((category) => {
return {
value: category.node.id,
label: category.node.name,
property: 'assetPriceCategory'
}
})
selected = { value: supplier.assetPriceCategory.id, label: supplier.assetPriceCategory.name }
<Select name="assetPriceCategory"
instanceId={useId()}
value={selected}
options={options}
onChange={option => supplierDataChange(option)}
/>
This works, the select shows and the options show, and the selected item is selected. My onChange:
const supplierDataChange = (object) => {
if(typeof supplier[object.property] === 'object') {
supplier[object.property].id = object.value
} else {
supplier[object.property] = object.value
}
}
Doing console.log() at the end of this function proves that the supplier has changed, but the <Select> object does not update, it remains the same option as loaded in the beginning.

Semantic UI dropdown not setting value after selecting option

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

React select set value in select

As I understood, in react-select (latest) you need to send an object to the value props, to select/preselect an option. I am also using react-hook-form for my form management.
Is it possible to set the value through react-select or do I need to use react-hook-form's setValue()
As I click on an Item, I send this to my states:
const handleSectionOnClick = (id) => {
setTravelRoute({
'LocationEnd': { value: +travelRoutes[id].LocationIdEnd, label: travelRoutes[id].LocationCityEnd },
'LocationStart': { value: +travelRoutes[id].LocationIdStart, label: travelRoutes[id].LocationCityStart },
'startDate': new Date(),
'endDate': new Date()
})
}
My Demo object looks like this:
{
'LocationCityEnd': "Berlin, Ger",
'LocationCityStart': "Hattingen, Ger",
'LocationIdEnd': 2,
'LocationIdStart': 1,
'startDate': new Date(),
'endDate': new Date()
}
My (LocationStart) select component looks like this:
<Controller
render={({ onChange }) => (
<Select
styles={customStyles}
onChange={handleOnChangeStartLocation}
name="startLocation"
value={travelRoute?.LocationStart}
options={selectOptions}
placeholder="Choose..."
/>
)}
name="startLocation"
className={`${errors.startLocation ? 'inputSelectError' : ''}`}
control={control}
rules={{ required: true }}
/>
Nothing gets selected, not even the value/label.
What Am I missing? Thank you!
EDIT:
I added the handleOnChangeStartLocation function:
const handleOnChangeStartLocation = e => {
const { value, label } = e;
setTravelRoute(prevState => ({
...prevState,
LocationIdStart: value,
LocationCityStart: label
}))
}
The problem seems to be that you are not updating LocationStart with the new value/label. You should do something like:
const handleOnChangeStartLocation = e => {
const { value, label } = e;
setTravelRoute(prevState => ({
...prevState,
LocationStart: e, // add this line of code
LocationIdStart: value,
LocationCityStart: label
}))
}

How to select text to copy without triggering click event in reactjs

I am using react-table. I have defined onRowClick() function for a column. Here select text should highlight the text and clicking have to redirect to another page. Now when I try to select the text, its getting redirected. How to select text without triggering click event?
Following is my onRowClick function:
onRowClick = (state, rowInfo, columnInfo) => {
return {
onClick: (e, handleOriginal) => {
if (columnInfo.id) {
this.props.history.push(`/downloads/${rowInfo.original.id}`);
} else if (handleOriginal) {
handleOriginal();
}
}
};
}
The following is my react-table component:
<ReactTable
manual
getTdProps = {this.onRowClick}
data = {results}
onFetchData = {this.onFetchData}
sortable = {false}
showPagination = {false}
noDataText = 'no data found'
columns = {[
{
Header: 'Id',
maxWidth: 50,
accessor: "id",
Cell: (props) => <span className="btn-link pointer">{props.value} </span>
},
{
Header: 'Processed on',
maxWidth: 165,
accessor: "created_at",
Cell: (props) => <span> {this.getDateTime(props.value)} </span>
}
]
/>
Clicking on id column should redirect to the details page. Selecting text should select the id text.
I think onclick cannot be prevented but your desired result can be obtained by using Window.getSelection() method.
The Window.getSelection() method returns a Selection object representing the range of text selected by the user or the current position of the caret.
By using this method you can get the selected text and then you can calculate its length as:
window.getSelection().toString()
And then you can modify your onRowClick method as given below:
onRowClick = (state, rowInfo, columnInfo) => {
return {
onClick: (e, handleOriginal) => {
let selection = window.getSelection().toString();
if(selection.length <= 0) {
if (columnInfo.id && selection.length > 0) {
console.log("columnInfo.id", columnInfo.id);
this.props.history.push(`/downloads/${rowInfo.original.id}`);
} else if (handleOriginal) {
handleOriginal();
console.log("columnInfo.id", "nothing");
}
}
}
};
};
I have created a working demo.

Optional field inside Options React Select

Hey guys im trying to create a autosuggestion in cooperation with redux-form. Im using the Creatable approach. I loading my options via an external API. The problem is, i need a extra field in every Option Object. {value: "test#gmx.de", label: "test#gmx.de", dn:"CN...." }. Is there a possibility to do so?
I typically add my own properties inside the callback for the API request, just before setting the options in the state. For example...
axios.get('/some/api/request')
.then(response => {
const options = response.data.map(item => {
// Add whatever custom properties you want here
return ({value: "test#gmx.de", label: "test#gmx.de", dn:"CN...." })
})
// set your options in the state to the new options constant from above
dispatch(change('formName', 'options', options))
Hope this helps!
//Handle change with either selectedOption
handleChange(selectedOption){
this.setState({ selectedOption })
if(this.props.onOptionSelect){
this.props.onOptionSelect(selectedOption.data)
}
}
loadOptions(input, callback) {
this.props.loadOptions(input).then(options => {
callback(null, {options: options})
})
}
render() {
const {selectedOption} = this.state
const selectClass = this.props.meta.touched && this.props.meta.error ? "has-error form-group" : "form-group"
return (
<div className={selectClass}>
<AsyncCreatable
value={selectedOption}
onChange={this.handleChange}
loadOptions={this.loadOptions}
isLoading={false}
placeholder={this.props.label}
promptTextCreator={(label) => this.props.promtLabel(label)}
onBlur={() => this.props.input.onBlur(selectedOption.value || "")}
/>
</div>
)
}
//Function to convert incomming users in usable options (React Select)
export const convertADUsersToOptions = users => {
return users.map(user => {
return {
value: normalizeDN(user.dn),
label: user.mail
}
})
}

Resources