Changing state for multiple elements in page - javascript

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
}]

Related

How can I change the Boolean value of an object to true via onClick?

I'm creating a Shopping Cart and I have three components.
The first component is an object which carries data of recent video games.
VideoGameList.js
const VideoGameList = [
{
id: 1,
title: "Fire Emblem Engage",
price: 59.99,
inCart: false,
},
{
id: 2,
title: "Pokemon Violet",
price: 59.99,
inCart: false,
},
];
The second component is the main Video Game page which displays each video game in a nice div. Inside of each div is an Add to Cart button which, if clicked, is meant to set the value of inCart (of that object) from false to true but I'm having trouble. This is the code I'm using.
VideoGame.js
const VideoGame = () => {
const [cart, setCart] = useState(VideoGameList);
const handleCartStatus = (cart) => {
setCart((prevState) =>
prevState.map((value) => {
if (value.id === cart.id) {
return {
...value,
inCart: !value.inCart,
};
}
return value;
})
);
};
return (
<>
<Header />
<div>
{VideoGameList.map(
({ id, title, price, inCart }, index) => (
<div>
<img key={src} src={src} alt={title} />
<div>
<p>{title}</p>
<p>{releaseDate}</p>
</div>
<div>
<p>${price}</p>
<button
onClick={() => handleCartStatus(cart)}
>
Add to Cart
</button>
</div>
</div>
)
)}
</div>
</>
);
};
My handleCartStatus function is meant to map through the entire VideoGameList array and check for the value of inCart and change the status from false to true if the id of the object I'm clicking matches the one in the array. I added the function to the onClick and have been testing if the inCart boolean values change from false to true but they are not.
The reason I'm wanting to change the value from false to true brings me to my third and final component which is the ShoppingCart page which displays all VideoGameList objects with inCart values set to true in another nice div.
I feel something may be wrong with the useStatue(VideoGameList) because I'm importing the objects from another component but even adding the entire array to the useState doesn't fix anything. Please advice.

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.

how to select All checkbox based group in reactjs

I did initial state for select single checkbox .Here is my intial state
this.state = {
fruites: [
{ id: 1 , value: "banana", isChecked: false },
{ id: 2, value: "apple", isChecked: false },
{ id: 3,value: "mango", isChecked: false },
{ id: 4, value: "grap", isChecked: false }
]
};
}
Method: I just this for selected all checkbox
handleAllChecked = id => event => {
let fruites = this.state.fruites;
fruites.forEach(fruite => {
data.filter(item =>
fruite.isChecked = event.target.checked;
});
});
this.setState({ fruites: fruites });
};
I just this method for individual checkbox .
handleCheckChieldElement = event => {
let fruites = this.state.fruites;
fruites.forEach(fruite => {
if (fruite.value === event.target.value)
fruite.isChecked = event.target.checked;
});
this.setState({ fruites: fruites });
};
Render:Here is my UI, I want to select All checkbox based on group . For example , I have got two group of value - such as Group , Topgroup. The problem is that , When I click on the group , it will select All checkbox including Topgroup and also I click banana , it will select all banana , I don't want to get all banana when click on one item. I don't to want to get topgroup checkbox when I select on the group.
{[{ id: 1, name: "group" }, { id: 2, name: "topGropup" }].map(item => (
<div>
<input
type="checkbox"
onChange={this.handleAllChecked(item.id)}
value="checkedall"
/>{" "}
{item.name}
<ul>
{this.state.fruites.map((fruite, index) => {
return (
<CheckBox
key={index}
handleCheckChieldElement={this.handleCheckChieldElement}
{...fruite}
/>
);
})}
</ul>
</div>
))}
</div>
How can I resolve this problem . Here is my codesanbox : https://codesandbox.io/s/react-multi-select-checkbox-or6ko
Here, I edited your codesandbox: https://codesandbox.io/s/react-multi-select-checkbox-bbuky
Basically you have 8 checkboxes, even though its 4 items displayed, duplicated for each group.
I added the 4 missing items in your state, but you'd actually want some kind of factory function that lets you create your state given the groups you have.
I had to edit some of your values since you were relying on stuff that now is not unique anymore, like value and use the group's id for example to create a unique identifier groupId-itemId.
Memory pointer to the same list
The groups in the app have the same pointer to memory list of fruits.
because of that the updates will affect on both groups.
See how I fixed it:
https://codesandbox.io/s/react-multi-select-checkbox-r29d1
I found some things in the app that can be improve so I improve them for example:
label to input checkbox to be able to click also on the text
I am here if you have any problem, I suggest you to learn Hooks.

How to add or remove form keys using react-final-form

single config example shows what configuration I use for inputs.
export const age = [
{
value: '',
type: 'radio',
name: 'age',
items: [
{value: 'kid', label: 'Im less than 18',
{value: 'adult', label: 'Im 18!',
],
},
];
export const someDate = [
{
type: 'date',
value: null,
name: 'someDate',
label: 'Enter date',
format: 'dd/MM/yyyy',
minDate: new Date('2019-12-31'),
maxDate: new Date('2020-03-31'),
validators: required.required.date
}
];
RFForm is a wrapper for rect-final-form Form component and I pass all components inside as children.
<RFForm
config={[...age, ...someDate, ...somethingElse]}
submit={submit}
>
<SectionBox title="Your age">
<Box mb={5}>
<InputList inputs={age}/>
</Box>
<SectionTitle title="Date"/>
<Box maxWidth="50%">
<InputList inputs={someDate}/>
</Box>
</SectionBox>
<SectionBox title="Something else">
<Box maxWidth="50%">
<InputList inputs={somethingElse}/>
</Box>
</SectionBox>
{
conditionToHideOrShowSection && <SectionWithInputs />
}
{
buttons
}
</RFForm>
I want to add a new section that will hide or show depends on what the user picks. The section should be ONLY present when the second radio button value is selected (adult). The section will contain a component with inputs from the configuration. All the fields should be required. This should only be validated when the section is present.
First question - how should I check if the specific radio button is checked. I don't have access to useForm from here and I need to hide or show section.
Second question - how to dynamically add new inputs when other inputs are changing. Remember that I have to add it to config (RFForm props) because initial value must be updated.
Actually you have access to it, but in other way via render method link
This sample shows how to conditionally show inputs link. Be aware if input hide back the data won't gone, it's still there , so to cleanup you should use change('inputName', undefined) (at least it helps me in my case)
At last you also should checkout about subscription prop. link

Is there any way I can use isMulti without it deleting choices I've already picked? In otherwords, having duplicate/repeated selected options?

Basically, I want to use the react-select library and use the isMulti prop, but the problem with that after selecting an option, the value would be deleted. As you can see below with the provided images, as soon as I click "US: 1" that option would go away. But for the app I'm trying to build, it's certainly possible for a customer to want 2 of the same sizes. Therefore they would pick 2 "US: 1" and it automatically sets the quantity to 2. The problem is that as soon as they pick "US: 1" that option goes away.
This is all I currently have now.
const options = [
{value: 1, label: "US: 1"},
{value: 1.25, label: "US: 1.25"},
{value: 1.5, label: "US: 1.5"},
{value: 1.75, label: "US: 1.75"},
{value: 2, label: "US: 2"},
{value: 2.25, label: "US: 2.25"},
]
class Details extends Component {
state={
selectedOption: []
}
handleChange = (selectedOption) => {
this.setState({ selectedOption: selectedOption });
}
render() {
<Select isMulti={true} isSearchable={true} onClick={value.changeSize(id, selectedOption)} value={selectedOption} onChange={this.handleChange} options={options}></Select>
}
}
Here's an example of what I'm talking about. "US: 1" goes away when it's clicked when I want that option to stay. I'm thinking it alters my "options" array and displaying the new one that doesn't have the clicked option. If I can somehow keep feeding it these original values after every single on onChange that would be awesome. I'm not sure how to dig into the library on how to do it or if it's even possible.
https://www.npmjs.com/package/react-select
Here how I would do it:
class Details extends Component {
state = {
selectedOption: []
};
handleChange = selectedOption => {
const newSelectedOption = selectedOption.map(opt => ({
label: opt.label,
innerValue: opt.value,
// I set a random value because it is needed to be able to delete the value without deleting all of them
value: Math.random()
}));
this.setState({ selectedOption: newSelectedOption });
};
render() {
return (
<Select
isMulti={true}
isSearchable={true}
value={this.state.selectedOption}
onChange={this.handleChange}
options={options}
/>
);
}
}
The idea is not to use value as it's original goal. When a label props is passed to value inside Select it still displays it correctly. So you will base yourself on innerValue and trick react-select.
Here a live example
I guess all you need is to add hideSelectedOptions={false} to <Select />.
Like:
<Select
isMulti={true}
hideSelectedOptions={false}
options={options}
...
/>

Categories

Resources