I want to add a small check/tick icon beside the value eg: Operations ✓ if user selects operations in the TopicList dropdownlist. The TopicList is a class component to get the data from the database which consist of: Operations, Array, Repetition, Function, Selection. If user selects 2 different values then eg: Operations ✓ Array ✓ Repetition Function Selection. How can I modify this code to solve this issue? Here is an image of how I would like it to be if user selects Array.
import axios from "axios";
import React, { useState } from "react";
import TopicList from "../Components/topicList";
import CheckIcon from '@mui/icons-material/Check';
function CreateEvent(success, message) {
const navigate = useNavigate();
const [selectedValues, setSelectedValues] = useState([]); // array to store selected values
const getDataFromTopicList = (val) => {
if (val !== "" && !selectedValues.includes(val)) {
setSelectedValues([...selectedValues, val]);
}
};
const handleSubmit = (event) => {
event.preventDefault();
console.log(selectedValues); // selectedValues array contains all selected values from all TopicList components
axios({
method: "POST",
url: BASE_URL "events/submitEvent",
data: {
topicId: selectedValues,
},
headers: { "Content-Type": "application/json" },
})
.then((response) => {
if (response.status === 200) {
toast.success("Successfully Created", {
position: toast.POSITION.TOP_CENTER,
});
} else {
toast.error(response.data.message, {
position: toast.POSITION.TOP_CENTER,
});
}
})
.catch((err) => {
if (err.response) {
toast.error(err.response.data.message, {
position: toast.POSITION.TOP_CENTER,
});
} else {
toast.error("Failed to Create", {
position: toast.POSITION.TOP_CENTER,
});
}
});
};
return (
<div className="">
<div>
<form
onSubmit={handleSubmit}
>
<h1>
Create an Event
</h1>
<div>
<div>
<TopicList
selectedValues={selectedValues}
getDataFromTopicList={getDataFromTopicList}
/>
</div>
</div>
</form>
</div>
</div>
);
}
export default CreateEvent;
import axios from "axios";
import React from "react";
import CheckIcon from "@mui/icons-material/Check";
const BASE_URL = process.env.REACT_APP_BASE_URL;
export default class TopicList extends React.Component {
state = {
topics: [],
};
componentDidMount() {
axios.get(BASE_URL `events/topic`).then((res) => {
const topics = res.data;
this.setState({ topics });
});
}
render() {
return (
<select required onChange={(val) => this.getCat(val.target.value)}>
{this.state.topics.map((topic) => (
<option value={topic.topicId}>
{topic.topic}
{this.props.selectedValues.includes(topic.topicId) && <CheckIcon style={{ color: "green" }} />}
</option>
))}
</select>
);
}
}
CodePudding user response:
Here you can see an example of a select with checkbox inside it. to see the code just click the link.
CodePudding user response:
It seems that the posted code has MUI but is not using its components in TopicList
.
Here is a basic example that makes use of the MUI Select
, and with implementation of the needed CheckIcon
on multiple selected values.
Minimized demo of below example: stackblitz
The example omitted the data fetching part for simplicity, but it keeps the same topics
state and get props for selectedValues
in TopicList
.
The update function for selectedValues
also changed for MUI component but the state value itself remained to be an array of selected topicId
, so hopefully it could be wired up for the data fetching without large refectoring of existing code.
Imports for MUI components in TopicList
:
import OutlinedInput from '@mui/material/OutlinedInput';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import ListItemText from '@mui/material/ListItemText';
import ListItemIcon from '@mui/material/ListItemIcon';
import Select from '@mui/material/Select';
import CheckIcon from '@mui/icons-material/Check';
The output of modified TopicList
:
<FormControl sx={{ m: 3, width: 300 }}>
<InputLabel id="topic-form-input-label">Topic</InputLabel>
<Select
labelId="topic-form-label"
id="multiple-topic-select"
multiple
value={this.props.selectedValues}
onChange={this.props.onChange}
input={<OutlinedInput label="Topic" />}
renderValue={(selected) =>
selected
.map((topicId) => {
const selectedTopic = this.state.topics.find(
(item) => item.topicId === topicId
);
return selectedTopic ? selectedTopic.topic : topicId;
})
.join(", ")
}
>
{this.state.topics.map((topic) => {
const selected = this.props.selectedValues.includes(topic.topicId);
return (
<MenuItem key={topic.topicId} value={topic.topicId}>
{selected && (
<ListItemIcon>
<CheckIcon style={{ color: "green" }} />
</ListItemIcon>
)}
<ListItemText inset={!selected} primary={topic.topic} />
</MenuItem>
);
})}
</Select>
</FormControl>
Selected values passed from the parent component:
const [selectedValues, setSelectedValues] = useState([]);
const handleChange = (event) => {
const {
target: { value },
} = event;
setSelectedValues(typeof value === "string" ? value.split(",") : value);
};
<TopicList
selectedValues={selectedValues}
onChange={handleChange}
/>