Update multiple semantic ui react dropdown keys to state - javascript

I'm using Semantic UI React to render some selection options in a dropdown .
I have a child component that is mapping over an array of object and returning some keys. So I supplied the following to the options prop for the semantic ui dropdown
<Dropdown
id="slotId"
value={slotId}
initialized={initialized}
onChange={onSlotIdChange}
selection
fluid
placeholder="Please select a slot id"
clearable
options={slots.map(slotId => {
return {
text: slotId.slotId,
value: slotId.slotId,
key: slotId.slotId,
description: `Initialized: ${slotId.initialized}`,
initialized: slotId.initialized
};
})}
/>
I'm lifting up state to the parent where I have the changeHandler defined
onSlotIdChange = async (e, { value, initialized }) => {
this.setState(
{ slotId: value, initialized: initialized, isLoading: false },
() => {
console.log(
"chosen slotId updated to state, callback -->",
this.state.slotId
);
console.log("initialized", this.state.initialized);
}
);
if (!value) {
this.handleClear();
return;
}
};
I have a codesanbox here with the issue.
Basically when I make the selection of the slotId it updates the slotId value to state, but I also want to update the initialized value to state as well. So For example, in the codesanbox, If you choose slotId: 1 from the dropdown I also want a state variable initialized to update with the value of Y.
I'm struggling with getting the initialized key from the child to update with the selected Id in the parent. It's only being set to an empty "" instead of the initialized value of Y or N.
I think the way semantic handles event changes only the value key is recognized

The reason was because on your Dropdown component's options, you value only includes the slotId:
options={slots.map(slot => {
return {
key: slot.slotId,
text: slot.slotId,
value: slot.slotId, // <--- this value here
description: `Initialized: ${slot.initialized}`,
initialized: slot.initialized
};
})}
To receive more information, you can either update the value returned:
<Dropdown
id="slotId"
value={slotId}
initialized={initialized}
onChange={onSlotIdChange}
selection
fluid
placeholder="Please select a slot id"
clearable
options={slots.map(slot => {
return {
key: slot.slotId,
text: slot.slotId,
value: { slotId: slot.slotId, initialized: slot.initialized },
description: `Initialized: ${slot.initialized}`,
initialized: slot.initialized
};
})}
/>
or pass in the third argument on onChange callback:
<Dropdown
id="slotId"
value={slotId}
initialized={initialized}
onChange={(e, d) => onSlotIdChange(e, d, slots.find(s => s.slotId === d.value).initialized)}
selection
fluid
placeholder="Please select a slot id"
clearable
options={slots.map(slot => {
return {
key: slot.slotId,
text: slot.slotId,
value: slot.slotId,
description: `Initialized: ${slot.initialized}`,
initialized: slot.initialized
};
})}
/>
or update the data returned to include with the found initialized value similar to the second approach above. Whichever that suits you best!

Related

Setting multiple selected values using React-select

I am having a dropdown where a user can add multiple dropdowns and select a value in it. While making a GET request, i wanted to keep the selected value in the dropdown, but not sure how to do it. I am able to make the selected value in a single dropdown, but finding it difficult to keep the selected value in multiple dropdowns.
I will be getting the value in an array like this
values = ["English","Ukraine","Japnese","Korean"];
Then in Select Dropdown for setting the single value i have written it like this:
options = [
{value: "english", label: "English"},
{value: "ukraine", label: "Ukraine"},
{value: "japnese", label: "Japnese"},
{value: "korean", label: "Korean"},
{value: "french", label: "French"}
];
<Select
className="profile-module-select-container"
classNamePrefix="profile-module-select"
options={options}
onChange={selected => {
this.handleDropdownSelect(selected, formKey);
}}
onMenuOpen={(e, i, o) => {
this.setState({
selectMenuOpen: true
});
}}
onMenuClose={() => {
this.setState({
selectMenuOpen: false
});
}}
name={name}
value={options.filter((items) => { return items.value === values })}
/>
values is an array and you would have to loop it over as well and filter it against Options . Considering the current implementation, it would be a nested loop, yes.

React Select defaultValue is set but doesn't appear

I've tried even manually setting the default values like in the documentation but no dice. I'm not sure if it's a styling issue or what. So below I posted what I have along with a screenshot.
<Select
components={animatedComponents}
getOptionLabel={convertToLabel}
getOptionValue={option => option.resource_name}
isMulti
onChange={changeEvent}
options={users}
theme={theme => ({
...theme,
borderRadius: 0
})}
defaultValue={(props.value || []).map(convertToValue)}
value={(props.value || []).map(convertToValue)}
/>
convertToValue function
const convertToValue = props => {
return {
label: `${props.name} ${props.family_name}`,
value: props.resource_name
};
};
convertToLabel function
const convertToLabel = props => {
return `${props.name} ${props.family_name}`;
};
changeEvent function
const changeEvent = (selectedOption, i) => {
let option = {
name: "reviewers",
value: selectedOption
};
update({ target: option });
};
users & props objects
users:
[
{
resource_name: "facebook_user1",
name: "Joe",
family_name: "Dirt"
},
{
resource_name: "facebook_user2",
name: "Trident",
family_name: "White"
}
]
props:
{
field: "placeholder",
fieldType: "placeholderType"
value:[
{
resource_name: "facebook_user1",
name: "Joe",
family_name: "Dirt"
},
{
resource_name: "facebook_user2",
name: "Trident",
family_name: "White"
}
]
}
What I see on my screen.
It is extremely difficult to tell exactly what your issue is, without seeing the actual JSX of your select render. Here are a few issues I see, looking at your question, and some hard guesses at what might be happening.
You should show us the full JSX render of your Select implementation
You never show us what your defaultValue prop looks like, but
remember that value is expected to be equal to one of your
options, not just an option 'value'
Your label and option getter
methods signature should be getOptionLabel = (option) => string and
getOptionValue = (option) => string. You've used props, which
might conflict with parent scope, in your instance.
You probably want
your convertToValue method signature to line up with those as well.
Your onChange event method signature doesn't line up with
React-Select, and may be causing you pain. See my answer to this
recent question for help on this.

How to call validation of Textbox on value change of other component in React.js?

Want to call validation of Textbox from value change of other custom component which sets value in state.
Handlers:
handleValueChange = (val, elementName) => {
this.setState({
...this.state,
[elementName]: val
});
};
handleSelectOptionTab = tab => {
console.log("tab : ", tab)//tab : {discountType: "Amount"}
this.setState({ ...this.state, ...tab });
};
Input components:
<Textbox
tabIndex="1"
name="discount"
id={"discount"}
type="number"
value={_.toString(this.state.discount)}
placeholder="Enter discount"
onChange={val => this.handleValueChange(val, "discount")}
onBlur={() => {}}
validate={this.state.validate}
validationCallback={res => {
this.setState({
...this.state,
hasDiscountError: res
});
}}
validationOption={
this.state.discountType === "Percent"
? {
name: "discount",
required: true,
reg: /regext-for-percent/,
regMsg:"validation msg 1"
}
: {
name: "discount",
required: true,
reg: /regex-for-amount/,
regMsg: "Validation msg 2"
}
}
/>
//Options: "Amount", "Percent"
//This is selectable optional buttons where user can choose anyone among multiple options (discountType: "Amount" or discountType: "Percent")
<OptionalButton
selection={this.state}
identifier={"discountType"}
tabIndex="2"
onSelect={tab => this.handleSelectOptionTab(tab)}
options={DISCOUNT_TYPES}
/>
Validation of Textbox is working fine on value change and focused out from Textbox but if value is already present and this.state.discountType is change from OptionalButton in that case validation is not working.
Example: Textbox value is 10000 with Type selected as "Amount" which is valid but as Type is changed to "Percent" then Textbox should show validation error.
You should also update this.state.validate after changing the tab. The issue is that the textbox is unaware that the tab change needs a revalidation, so you need to tell it using the this.state.validate value.
Change you handleSelectOptionTab method like this:
handleSelectOptionTab = tab => {
console.log("tab : ", tab)//tab : {discountType: "Amount"}
// try and use a function inside setState, instead of an object
this.setState(oldState => ({ ...oldState, ...tab, validate: true }));
};
and then inside your validationCallback
validationCallback={res => {
this.setState(oldState => ({
...oldState,
hasDiscountError: res,
validate: false // to not trigger another validation again
}));
}}
Maybe option component is change then trigger this.handleValueChange(val, "discount").
You use ref for reach component.
Following code to use ref
For example div element
const refTest = React.createRef<HTMLDivElement>()
And use for component
<div className="App" ref={refTest}>
I don't know which use to component so example is div element.
Then you should trigger "handleValueChange" event for "refTest" component

Changing state for multiple elements in page

In my react-app i have a list that is rendered dynamically from an array, each item has a checkbox and an input, the input by default is disabled, when i click on the checkbox this input should be enabled if it meets a specific condition, i have managed to do some of the work, but I'm facing some issues like when i click on one of the checkboxes all inputs get enabled, and this input has a value i want to be able to edit it but i can't here is the code:
Initial state
cards: [],
disabledInput: false
Mapping the list:
return this.state.cards.map(card => (
<Checkbox key={card.id} onClick={this.setState({ disabledInput: true })} />
<Input value={this.state.card.name} disabled={this.state.disabledInput} onChange={e => this.setState({ text: e.target.value })} />
));
You need to keep the initial disable states of each checkbox true as an array and map that individually into each checkbox.
cards = [{
name: 'card 1',
disabledInput: true
}, {
name: 'card 2',
disabledInput: true
}]
changeDisableState = (i) => {
let cards = this.state.cards;
cards[i].disabledInput = !cards[i].disabledInput;
this.setState({cards});
}
return this.state.cards.map((card, i) => (
<Checkbox key={card.id} onClick={() => this.changeDisableState(i)} />
<Input value={card.name} disabled={card.disabledInput}/>
));
Edited: Instead of a separate array you can keep a disable field inside the card state itself.
Each checkbox should have a boolean to manage its own state (checked or not). I created a Codesandbox that should solve your problem
You need to maintain a disabledInput flag for each card, at the minute you only have one across all cards.
Your card state should look something like -
cards = [{
name: 'card 1',
disabledInput: false
}, {
name: 'card 2',
disabledInput: true
}]

send the value as string when selecting the option

I am using react-select for autocomplete and option related field. When i select the option it passes whole that option object as {value: 'abc', label: 'ABC'} but i wanted only to pass the value as a string not the object. Thus, i used getOptionValue but it is not working as expected.
This is what I have done
<Field
name='status'
component={SearchableText}
placeholder="Search..."
options={status}
styles={styles}
getOptionLabel={option => option.label}
getOptionValue={option => option.value}
/>
I have used both getOptionLabel and getOptionValue but is still passing the selected option in object form instead of just the value as string.
Expected one
status: 'active'
Current behavior
status: { value: 'active', label: 'Active'}
I couldn't find getOptionValue in the docs for react-select, but you could always create an adapter around react-select. i.e. create your own Select component that uses react-select's Select component internally. After doing this it becomes possible to create your own getOptionValue. You can use this to make sure the value is a string.
import React from "react";
import Select from "react-select";
class MySelect extends React.Component {
getSelectValue() {
return this.props.options.find(
option => this.props.getOptionValue(option) === this.props.input.value
);
}
render() {
console.log("value", this.props.input.value);
return (
<Select
value={this.getSelectValue()}
onChange={option => {
this.props.input.onChange(this.props.getOptionValue(option));
}}
options={this.props.options}
/>
);
}
}
MySelect.defaultProps = {
getOptionValue: v => v
};
const MyForm = reduxForm({ form: "MyForm" })(
class extends React.PureComponent {
render() {
return (
<Field
name="myCoolSelect"
component={MySelect}
options={[
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" }
]}
getOptionValue={option => option.value}
/>
);
}
}
);
The above is a basic example of how to get this working. You may want to pass other input or meta props to take advantage of other redux-form features. e.g. onBlur, onFocus, etc. You can see it in action here: https://codesandbox.io/s/6wykjnv32n

Categories

Resources