How to change the State of option separately, so that the behavior should be based on option which means only one configurable option can be selected?
Use case scenario:
- Nothing selected, validate to select Color and Size
- Either Color or Size selected validate one option which was not selected.
This is what I'm trying to achieve:
JSON:
{
"configurable_options": [
{
"__typename": "ConfigurableProductOptions",
"id": 167,
"attribute_id": "93",
"label": "Color",
"position": 1,
"use_default": false,
"attribute_code": "color",
"values": [
{
"__typename": "ConfigurableProductOptionsValues",
"value_index": 50,
"label": "Blue",
"swatch_data": {
"__typename": "ColorSwatchData",
"value": "#1857f7"
}
},
{
"__typename": "ConfigurableProductOptionsValues",
"value_index": 53,
"label": "Green",
"swatch_data": {
"__typename": "ColorSwatchData",
"value": "#53a828"
}
},
{
"__typename": "ConfigurableProductOptionsValues",
"value_index": 56,
"label": "Orange",
"swatch_data": {
"__typename": "ColorSwatchData",
"value": "#eb6703"
}
}
],
"product_id": 1194
},
{
"__typename": "ConfigurableProductOptions",
"id": 166,
"attribute_id": "144",
"label": "Size",
"position": 0,
"use_default": false,
"attribute_code": "size",
"values": [
{
"__typename": "ConfigurableProductOptionsValues",
"value_index": 166,
"label": "XS",
"swatch_data": {
"__typename": "TextSwatchData",
"value": "XS"
}
},
{
"__typename": "ConfigurableProductOptionsValues",
"value_index": 167,
"label": "S",
"swatch_data": {
"__typename": "TextSwatchData",
"value": "S"
}
},
{
"__typename": "ConfigurableProductOptionsValues",
"value_index": 168,
"label": "M",
"swatch_data": {
"__typename": "TextSwatchData",
"value": "M"
}
},
{
"__typename": "ConfigurableProductOptionsValues",
"value_index": 169,
"label": "L",
"swatch_data": {
"__typename": "TextSwatchData",
"value": "L"
}
},
{
"__typename": "ConfigurableProductOptionsValues",
"value_index": 170,
"label": "XL",
"swatch_data": {
"__typename": "TextSwatchData",
"value": "XL"
}
}
],
"product_id": 1194
}
]
}
import {
Box,
Button,
Container,
Stack,
ToggleButton,
ToggleButtonGroup,
} from "@mui/material";
import { ReactElement, useState } from "react";
import products from "../utils/data.json";
const ProductDetail = (): ReactElement => {
const [selectedProductOptions, setSelectedProductOptions] = useState<any>();
const [cartItems, setCartItems] = useState<any>();
const handleOption = (
event: React.MouseEvent<HTMLElement>,
newOption: any
) => {
setSelectedProductOptions(newOption);
};
const addToCart = () => {
setCartItems(selectedProductOptions);
};
console.log("cartItems", cartItems);
return (
<>
<Box>
<Container maxWidth="sm">
{products.configurable_options.map((product: any, index: number) => (
<Stack
key={index}
direction="row"
alignItems="center"
justifyContent="left"
>
<ToggleButtonGroup
sx={{ mt: 5 }}
color="primary"
exclusive
aria-label="Platform"
onChange={handleOption}
>
{product.values.map((item: any, index: number) => (
<ToggleButton key={index} value={item}>
{item.label}
</ToggleButton>
))}
</ToggleButtonGroup>
</Stack>
))}
<Button variant="contained" sx={{ mt: 5 }} onClick={addToCart}>
Add To Cart
</Button>
</Container>
</Box>
</>
);
};
export default ProductDetail;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
CodePudding user response:
Create an initial state object that is derived from data.json
.
eg {166: null, 167: null}
Then onChange, set the product's value_index
as the selected state on the configurable_option.id
key within selectedProductOptions
.
eg clicking "Orange" would set selectedProductOptions
to {166: null, 167: 56}
import products from "./data.json";
const initialState = {};
products.configurable_options.forEach(({ id }) => {
initialState[id] = null;
});
const ProductDetail = () => {
const [selectedProductOptions, setSelectedProductOptions] = useState(
initialState
);
return (
<Container maxWidth="sm">
{products.configurable_options.map((configurable_option) => (
<div>
<ToggleButtonGroup
sx={{ mt: 5 }}
color="primary"
onChange={(_event, value) => {
setSelectedProductOptions({
...selectedProductOptions,
[configurable_option.id]: value[0].value_index
});
}}
>
{configurable_option.values.map((item, index) => (
<ToggleButton
key={index}
value={item}
selected={
selectedProductOptions[configurable_option.id] ===
item.value_index
}
>
{item.label}
</ToggleButton>
))}
</ToggleButtonGroup>
</div>
))}
</Container>
);
};