new react hooks(typescript) developer here, could somebody suggest on how to implement this: when user has chosen from select option(antd) then the button becomes red and can be clicked, that button should take one to that specific option what he chose (id?) with this?:
history.push(`/info/${....id}`); ??
my code :
import React, { useState } from "react";
import "antd/dist/antd.css";
import { Select } from "antd";
import { useHistory, useRouteMatch } from "react-router-dom";
const { Option } = Select;
const history = useHistory();
function EventsSection() {
const anarray = [
{ name: "obama", address: "usa", id: "81" },
{ name: "obama", address: "usa", id: "86" },
{ name: "putin", address: "russia", id: "91" },
{ name: "erdogan", address: "turkey", id: "31" },
{ name: "jebordoq", address: "alien", id: "29" },
];
return (
<section>
{/* this button becomes red then we know somebody has clicked something from select options */}
<button>if i'm red click me</button>
<Select
className="senderId"
style={{ width: "100%" }}
placeholder="Hide Me"
mode="multiple"
open={true}
listHeight={350}
>
{anarray.map((item, idx) => (
<Option
style={{ width: "100%", height: "100%" }}
className="options"
key={idx}
value={item.id}
>
{item.name}
<br></br>
{item.address}
<br></br>
</Option>
))}
</Select>
</section>
);
}
export default EventsSection;
ask me if needed
Related
im triying to select by default a value into a select input but the input is not recognizing that value until i change it manually. By the default i set "All" as my default value. here is my code and the codesandbox link:
import "./styles.css";
import React, { useState, useEffect } from "react";
import { FormField } from "react-form-input-fields";
import "react-form-input-fields/dist/index.css";
export default function App() {
let [type, setType] = useState("All");
const types = [
{ label: "All", value: "All" },
{ label: "Afganistan", value: "Afganistan" },
{ label: "Albania", value: "Albania" },
{ label: "Algeria", value: "Algeria" },
{ label: "American Samoa", value: "American Samoa" },
{ label: "Andorra", value: "Andorra" },
{ label: "Angola", value: "Angola" }
];
function handletype(e) {
setType(e);
}
return (
<div className="App">
{/* <h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2> */}
<FormField
type="select"
value={type}
option={types}
label={"Select your type"}
keys={"label"}
handleOnChange={(value) => handletype(value)}
/>
</div>
);
}
link:
https://codesandbox.io/s/select-problem-ykplcm
The library you use has a bug
The source code reveals that the value prop is only checked in componendDidUpdate, but this hooks is not called for the initial render
I would rather use a different library
I am using material ui and reactjs for having grouped autocomplete.
Below is the code.
import * as React from "react";
import TextField from "#mui/material/TextField";
import Autocomplete from "#mui/material/Autocomplete";
import Typography from "#material-ui/core/Typography";
export default function Grouped() {
top100Films = top100Films.sort((a, b) =>
a.genre.toLowerCase() > b.genre.toLowerCase() ? 1 : -1
);
return (
<Autocomplete
id="grouped-demo"
options={top100Films}
groupBy={(option) => option.genre}
getOptionLabel={(option) => option.title}
sx={{ width: 300 }}
renderInput={(params) => (
<TextField {...params} label="With categories" />
)}
/>
);
}
// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
let top100Films = [
{ title: "The Shawshank Redemption", genre: "thriller" },
{ title: "The Dark Knight", genre: "super hero" },
{ title: "The Godfather: Part II", genre: "thriller" },
{ title: "12 Angry Men", genre: "war" },
{ title: "Schindler's List", genre: "war" },
{ title: "superman", genre: "super hero" },
{ title: "The Godfather", genre: "thriller" },
{
title: "The Lord of the Rings: The Return of the King",
genre: "adventure"
}
];
Below is the link to codesandbox
https://codesandbox.io/s/fontsize-8n6ovr?file=/demo.js:0-1195
I only want to change font size of groupBy and options text, without changing the size of input box.
Tried using Typography but wasn't able to achieve it. Please help me do it.
Thanks in advance!
You could use renderGroup prop
The prop type is function whose signature is
function(params: AutocompleteRenderGroupParams) => ReactNode
And according to the type definition of AutocompleteRenderGroupParams, we could know the properties of params
export interface AutocompleteRenderGroupParams {
key: string;
group: string;
children?: React.ReactNode;
}
From all the given, we could customize the group render accordingly
renderGroup={(params) => (
<Box key={params.key}>
<Typography fontSize={20} fontStyle="italic" p={1}>
{params.group}
</Typography>
{params.children}
</Box>
)}
Codesandbox Demo
References
Autocomplete API, where we could find detail info for renderGroup prop
Autocomplete.d.ts, where we could find type definition for AutocompleteRenderGroupParams
#hgb123 thank you for helping.
Extending his answer, Below is the code for both options and groupBy text including class based and hooks based component
class based component
import * as React from "react";
import TextField from "#mui/material/TextField";
import Autocomplete from "#mui/material/Autocomplete";
import Typography from "#mui/material/Typography";
import Box from "#mui/material/Box";
import { withStyles } from "#material-ui/core/styles";
const useStyles = (theme) => ({
option: {
fontSize: "20px"
}
});
class Grouped extends React.Component {
top100Films = top100Films.sort((a, b) =>
a.genre.toLowerCase() > b.genre.toLowerCase() ? 1 : -1
);
render() {
const { classes } = this.props;
return (
<Autocomplete
classes={{ option: classes.option }}
id="grouped-demo"
options={top100Films}
groupBy={(option) => option.genre}
getOptionLabel={(option) => option.title}
sx={{ width: 300 }}
renderInput={(params) => (
<TextField {...params} label="With categories" />
)}
renderGroup={(params) => (
<Box key={params.key}>
<Typography fontSize={40}>{params.group}</Typography>
{params.children}
</Box>
)}
/>
);
}
}
// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
let top100Films = [
{ title: "The Shawshank Redemption", genre: "thriller" },
{ title: "The Dark Knight", genre: "super hero" },
{ title: "The Godfather: Part II", genre: "thriller" },
{ title: "12 Angry Men", genre: "war" },
{ title: "Schindler's List", genre: "war" },
{ title: "superman", genre: "super hero" },
{ title: "The Godfather", genre: "thriller" },
{
title: "The Lord of the Rings: The Return of the King",
genre: "adventure"
}
];
export default withStyles(useStyles)(Grouped);
// incase of redux
// import { compose } from 'redux';
// export default compose(connect(mapStateToProps, mapDispatchToProps),withStyles(useStyles))(Grouped)
Hooks based component
import * as React from "react";
import TextField from "#mui/material/TextField";
import Autocomplete from "#mui/material/Autocomplete";
import Typography from "#mui/material/Typography";
import Box from "#mui/material/Box";
import { makeStyles } from "#material-ui/core/styles";
useStyles = makeStyles(() => ({
// stands for .MuiAutocomplete-option
option: {
fontSize: "20px"
}
}));
export default function Grouped() {
top100Films = top100Films.sort((a, b) =>
a.genre.toLowerCase() > b.genre.toLowerCase() ? 1 : -1
);
const classes = useStyles();
return (
<Autocomplete
classes={{ option: classes.option }}
id="grouped-demo"
options={top100Films}
groupBy={(option) => option.genre}
getOptionLabel={(option) => option.title}
sx={{ width: 300 }}
renderInput={(params) => (
<TextField {...params} label="With categories" />
)}
renderGroup={(params) => (
<Box key={params.key}>
<Typography fontSize={40}>
{params.group}
</Typography>
{params.children}
</Box>
)}
/>
);
}
// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
let top100Films = [
{ title: "The Shawshank Redemption", genre: "thriller" },
{ title: "The Dark Knight", genre: "super hero" },
{ title: "The Godfather: Part II", genre: "thriller" },
{ title: "12 Angry Men", genre: "war" },
{ title: "Schindler's List", genre: "war" },
{ title: "superman", genre: "super hero" },
{ title: "The Godfather", genre: "thriller" },
{
title: "The Lord of the Rings: The Return of the King",
genre: "adventure"
}
];
Below is the link to codesandbox
https://codesandbox.io/s/fontsize-forked-qhyvkn?file=/demo.js
We can also do it without styles (withStyles, useStyles) by removing classes={{ option: classes.option }} from Autocomplete and its related code from the file and adding Typography in renderGroup <Typography fontSize={40}> {params.children}<Typography fontSize={40}>
renderGroup={(params) => (
<Box key={params.key}>
<Typography fontSize={40}>
{params.group}
</Typography>
<Typography fontSize={40}> //adding this
{params.children}
<Typography fontSize={40}>
</Box>
)}
/>
Hope this helps someone!
I have a set of select menus and I am trying to change a value when I select an option using onChange={updateValue} event. When I first select an option, the value is not being updated in the select menu.
It only changes the second time I try to choose an option. Not sure what I am doing wrong.
Edit: I did some more research (OnChange event using React JS for drop down) and I believe I need the value of the select to be updated as well, using setState. I cant figure out how to do it without having a variable for each value and set the state again.
let selectMenus = [
{
id: 'id1',
name: 'name1',
label: 'label1',
value: '0',
options: [
{
text: 'All ages',
value: '0',
},
{
text: '35 - 37 yrs',
value: '1',
},
],
buttonLabel: 'Refresh',
},
{
id: 'id2',
name: 'name2',
label: 'label2',
value: '1',
options: [
{
text: 'All ages',
value: '0',
},
{
text: '45 - 50 yrs',
value: '1',
},
],
buttonLabel: 'Refresh',
},
];
const [url, setUrl] = useState('http://localhost:5000/selectDropdowns1');
const updateValue = () => {
setUrl('http://localhost:5000/selectDropdowns2');
};
<form>
{selectMenus.map((select) => (
<div key={select.id} className='select-container'>
<label htmlFor={select.id}>{select.label}</label>
<select id={select.id} name={select.name} value={select.value} onChange={updateValue}>
{select.options.map((option) => (
<option value={option.value} key={uuid()}>
{option.text}
</option>
))}
</select>
<button>{select.buttonLabel}</button>
</div>
))}
</form>;
The problem is that when you provide onChange prop to select component it become a controlled component.
For more information: React Docs - Forms #controlled components
When you dealing with controlled components you must provide a value to it and when onChange triggerd it should update that value to work properly. Since you did not provide the full code, I imagine you have an array of select menus and options attached to it.
So in this case every select component should have own onChange method and own value to work properly. To achive this we should create another component for only Select Options. Like this;
function SelectComponent({ optionList, onSelected }) {
const [value, setValue] = useState();
const updateValue = ({ target }) => {
setValue(target.value);
if (onSelected) onSelected(target.value);
};
return (
<>
<label htmlFor={optionList.id}>{optionList.label}</label>
<select
id={optionList.id}
name={optionList.name}
value={value}
onChange={updateValue}
>
{optionList.options.map((option) => (
<option value={option.value} key={uuid()}>
{option.text}
</option>
))}
</select>
<button>{optionList.buttonLabel}</button>
</>
);
}
This component accepts to props; optionList and onSelected
optionList is the list of options to render
onSelected is a method that we call when user select and option
On main component, we should change the select section with our select component with props optionList and onSelected
return (
<div>
{selectMenus.map((select) => (
<div key={select.id} className="select-container">
<SelectComponent optionList={select} onSelected={updateValue} />
</div>
))}
</div>
);
So overall code is like this:
import { useState } from "react";
import { v4 as uuid } from "uuid";
export default function App() {
const [url, setUrl] = useState();
const updateValue = (value) => {
setUrl(value);
};
const selectMenus = [
{
id: 1,
label: "Menu 1",
name: "menu1",
buttonLabel: "Menu 1",
options: [
{
text: "option 1",
value: "option1"
},
{
text: "option 2",
value: "option2"
},
{
text: "option 3",
value: "option3"
}
]
},
{
id: 2,
label: "Menu 2",
name: "menu2",
buttonLabel: "Menu 2",
options: [
{
text: "option 1",
value: "option1"
},
{
text: "option 2",
value: "option2"
},
{
text: "option 3",
value: "option3"
}
]
},
{
id: 3,
label: "Menu 3",
name: "menu3",
buttonLabel: "Menu 3",
options: [
{
text: "option 1",
value: "option1"
},
{
text: "option 2",
value: "option2"
},
{
text: "option 3",
value: "option3"
}
]
}
];
return (
<div className="App">
<h1>URL Value: {url}</h1>
{selectMenus.map((select) => (
<div key={select.id} className="select-container">
<SelectComponent optionList={select} onSelected={updateValue} />
</div>
))}
</div>
);
}
function SelectComponent({ optionList, onSelected }) {
const [value, setValue] = useState();
const updateValue = ({ target }) => {
setValue(target.value);
if (onSelected) onSelected(target.value);
};
return (
<>
<label htmlFor={optionList.id}>{optionList.label}</label>
<select
id={optionList.id}
name={optionList.name}
value={value}
onChange={updateValue}
>
{optionList.options.map((option) => (
<option value={option.value} key={uuid()}>
{option.text}
</option>
))}
</select>
<button>{optionList.buttonLabel}</button>
</>
);
}
Working example is overhere codesandbox
I am trying to display the shoe array item's data if the color property matches the radio button color that is clicked. If the black radio button is selected, the array item with the black color property value should show.
(Note: How can I display or render the shoe data)
Thanks in advance!
App.js
import React, { Component } from "react";
class CheckColor extends Component {
constructor(props) {
super(props)
this.state = {
color: '',
shoes: [
{name: 'Black Shoe', color: 'Black', price: 180},
{name: 'Red Shoe', color: 'Red', price: 120},
{name: 'White Shoe', color: 'White', price: 100}
]
}
this.handleColorChange = this.handleColorChange.bind(this)
}
handleColorChange(e) {
const color = e.target.value
this.setState({ color: color })
}
render() {
const colors = ['Black', 'Red', 'White']
return(
<form>
{colors.map((color, index) =>
<label key={index}>
{color}
<input
value={color}
checked={this.state.color === color}
onChange={this.handleColorChange}
type="radio"
/>
</label>
)}
</form>
)
}
}
export default class App extends Component {
render() {
return (
<div className="App">
<CheckColor />
</div>
);
}
}
You can filter the colors based on the selected color values and then just use a map for showing the filtered shoes.
import React, { Component } from "react";
class CheckColor extends Component {
constructor(props) {
super(props);
this.state = {
color: "",
shoes: [
{ name: "Black Shoe", color: "Black", price: 180 },
{ name: "Red Shoe", color: "Red", price: 120 },
{ name: "White Shoe", color: "White", price: 100 }
]
};
this.handleColorChange = this.handleColorChange.bind(this);
}
handleColorChange(e) {
const color = e.target.value;
console.log(color);
this.setState({ color: color });
}
render() {
const colors = ["Black", "Red", "White"];
const shoesToShow = this.state.shoes.filter(item => ( item.color === this.state.color));
console.log(shoesToShow);
return (
<>
<form>
{colors.map((color, index) => (
<label key={index}>
{color}
<input
value={color}
checked={this.state.color === color}
onChange={this.handleColorChange}
type="radio"
/>
</label>
))}
</form>
{shoesToShow.map(shoe => (
<div>{shoe.name} </div>
))}
</>
);
}
}
Four Steps to display object as input radio dynamically
// 1. obj data
const phoneNums = {
jim: {
type: "Mobile",
value: 4153662323
},
tim: {
type: "Business",
value: 4153662323
},
}
//2. convert obj to array
const radioNumArr = Object.keys(phoneNums).map(i => phoneNums[i]);
// 3. Set data to User State via Hook
setRadioData(radioNumArr );
// 4.set hook and loop on radiodata
const [radioData, setRadioData] = useState([]);
<div>
{radioData.map((option) => (
<div className="forminputlabel" >
<input
type="radio"
name="dynamic-radio"
value={option.value}
/>
<label>{option.type} </label>
</div>
))}
</div>
I try to implement example of material-ui selector and got code-fragment from github example
import React from "react";
import {withStyles} from "material-ui/styles";
import Select from "material-ui/Select";
import styles from "../../overtimesStyles";
class DivisionReport extends React.Component {
state = {
selectedOption: "",
}
handleChange = (selectedOption) => {
this.setState({selectedOption});
// selectedOption can be null when the `x` (close) button is clicked
if (selectedOption) {
console.log(`Selected: ${selectedOption.label}`);
}
}
render() {
const {selectedOption} = this.state;
return (
<Select
name="form-field-name"
value={selectedOption}
onChange={this.handleChange}
options={[
{value: "one", label: "One"},
{value: "two", label: "Two"},
{value: "333", label: "One"},
{value: "444", label: "444"},
{value: "555", label: "555"},
{value: "666", label: "666"},
]}
/>
);
}
}
export default withStyles(styles)(DivisionReport);
But there is no items for selection which I expected to see:
Can you suggest why I met with this issue?
p.s. top component, which use DivisionReport is:
const OvertimesReport = ({handleChangeSelection, selectedOption, classes}) => (
<div className={classes.workarea}>
<Card>
<CardContent className="overtimes">
<DivisionReport handleChangeSelection={handleChangeSelection} selectedOption={selectedOption}/>
</CardContent>
</Card>
</div>
);
style is:
workarea: {
margin: "0px 5%",
},
You are trying to import the Select component from material-ui/Select, but you should import if from the react-select package instead:
import Select from "react-select";
Also note that the value key of an option is named value and the label key is named label, not valueKey and labelKey.
<Select
name="form-field-name"
value={selectedOption}
onChange={this.handleChange}
options={[
{value: "one", label: "One"},
{value: "two", label: "Two"},
{value: "333", label: "One"},
{value: "444", label: "444"},
{value: "555", label: "555"},
{value: "666", label: "666"},
]
}
/>
import Select from '#material-ui/core/Select';
Then in the render:
<Select
native
name="form-field-name"
value={selectedOption}
onChange={this.handleChange}
>
<option key="1" value="1"> 1 </option>
<option key="2" value="2"> 2 </option>
<option key="3" value="3"> 3 </option>
</Select>
Try this way, and let me know how it works