select input field always return undefined - javascript

when ever i try to select an option in input field it must set the state value to the selected option but it return undefined
I am using Semantic ui react Form to take input but when ever i select the option and submit it gives me undefined
import React from 'react'
import { Form, Input, TextArea, Button, Select, Container } from
'semantic-ui-react'
const RankOptions = [
{ key: 'lg', text: 'Lt-Gen', value: 'Lt-Gen' },
{ key: 'mg', text: 'Mj-Gen', value: 'Mj-Gen' },
{ key: 'b', text: 'Brig', value: 'Brig' },
{ key: 'col', text: 'Col', value: 'Col' },
{ key: 'lc', text: 'Lt-Col', value: 'Lt-Col' },
{ key: 'm', text: 'Major', value: 'Mj' },
{ key: 'capt', text: 'Capt', value: 'Capt' },
{ key: 'lt', text: 'Lt', value: 'Lt' },
{ key: '2lt', text: '2-Lt', value: 'Lt-2' },
]
export default class Employee extends React.Component{
state={}
handleSubmit = () => {
console.log(this.state)
}
handlerankChange = (e) => {
const value = e.target.value
this.setState({
rank : value
})
}
render() {
return (
<Container>
<Form size='huge'>
<Form.Group widths='equal'>
<Form.Field
name = 'rank'
control = {Select}
label = 'Rank'
options = {RankOptions}
placeholder = 'Rank'
value = {this.state.value}
onChange = {this.handlerankChange}
/>
<Button primary onClick=
{this.handleSubmit}>Submit</Button>
</Form>
</Container>
)
}
}
the state must be any option from ranks

A working code will help you out:
import React from "react";
import { render } from "react-dom";
import Hello from "./Hello";
import {
Button,
Form,
Grid,
Header,
Image,
Message,
Segment,
Label,
Dropdown
} from "semantic-ui-react";
import Select from "react-select";
import "./index.css";
const styles = {
fontFamily: "sans-serif",
textAlign: "center"
};
class App extends React.Component {
state = {
selectedOption: ""
};
handleChange = selectedOption => {
this.setState({ selectedOption });
};
render() {
const { selectedOption } = this.state;
const value = selectedOption && selectedOption.value;
return (
<div className="login-form">
<Grid
textAlign="center"
style={{ height: "100%" }}
verticalAlign="middle"
>
<Grid.Column style={{ maxWidth: 450 }} textAlign="left">
<Form size="large">
<Segment>
<div>
<Select
name="form-field-name"
value={value}
onChange={this.handleChange}
options={[
{ value: "one", label: "One" },
{ value: "two", label: "Two" }
]}
/>
</div>
</Segment>
</Form>
</Grid.Column>
</Grid>
</div>
);
}
}
render(<App />, document.getElementById("root"));
Source of the code on the codesandbox

Set initial value for rank in state as
state = {
rank:''
}
and change
<Form.Field
name = 'rank'
control = {Select}
label = 'Rank'
options = {RankOptions}
placeholder = 'Rank'
value = {this.state.rank}
onChange = {this.handlerankChange}
/>

you need not access the value by e.target.value, the callback provides object with key 'value';
eg:
import React from 'react'
import { Form, Input, TextArea, Button, Select, Container } from
'semantic-ui-react'
const RankOptions = [
{ key: 'lg', text: 'Lt-Gen', value: 'Lt-Gen' },
{ key: 'mg', text: 'Mj-Gen', value: 'Mj-Gen' },
{ key: 'b', text: 'Brig', value: 'Brig' },
{ key: 'col', text: 'Col', value: 'Col' },
{ key: 'lc', text: 'Lt-Col', value: 'Lt-Col' },
{ key: 'm', text: 'Major', value: 'Mj' },
{ key: 'capt', text: 'Capt', value: 'Capt' },
{ key: 'lt', text: 'Lt', value: 'Lt' },
{ key: '2lt', text: '2-Lt', value: 'Lt-2' },
]
export default class Employee extends React.Component{
state={}
handleSubmit = () => {
console.log(this.state)
}
handlerankChange = ({ value }) => {
this.setState({
rank : value
})
}
render() {
return (
<Container>
<Form size='huge'>
<Form.Group widths='equal'>
<Form.Field
name = 'rank'
control = {Select}
label = 'Rank'
options = {RankOptions}
placeholder = 'Rank'
value = {this.state.rank} // this should be rank
onChange = {this.handlerankChange}
/>
</Form.Group>.
<Button primary onClick=
{this.handleSubmit}>Submit</Button>
</Form>
</Container>
)
}
}
Hope this helps!!

Related

how can i solve a key value select input problem

im just testing this reactjs npm but when i use the select input it just show up de value pair insted of the label pair
this is the piece of the code:
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: "Skins", value: "outfit" },
{ label: "Banners", value: "banner" },
{ label: "Wraps", value: "wrap" },
{ label: "Sprays", value: "spray" },
{ label: "Emoji", value: "emoji" },
{ label: "Pickaxe", value: "pickaxe" },
{ label: "Gliders", value: "glider" },
{ label: "Loading screens", value: "loadingscreen" },
{ label: "Emotes", value: "emote" }
];
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={"country"}
handleOnChange={(value) => handletype(value)}
/>
</div>
);
}
here is the link from codesanbox
https://codesandbox.io/s/select-problem-ykplcm
i have trid using map and filter functions on value property component and i still dont get what i want.
Store the whole selected type in the state.
Then use type.label as the value.
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({ label: "All", value: "All" }); // The state contains an object.
const types = [
{ label: "All", value: "All" },
{ label: "Skins", value: "outfit" },
{ label: "Banners", value: "banner" },
{ label: "Wraps", value: "wrap" },
{ label: "Sprays", value: "spray" },
{ label: "Emoji", value: "emoji" },
{ label: "Pickaxe", value: "pickaxe" },
{ label: "Gliders", value: "glider" },
{ label: "Loading screens", value: "loadingscreen" },
{ label: "Emotes", value: "emote" }
];
function handletype(e) {
// Find the selected object based on the returned value
const selected = types.filter((type) => type.value === e)[0]
console.log(selected)
// Set state with it.
setType(selected);
}
return (
<div className="App">
{/* <h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2> */}
<FormField
type="select"
value={type.label} // The label property of the stored state is used here
option={types}
label={"Select your type"}
keys={"country"}
handleOnChange={(value) => handletype(value)}
/>
</div>
);
}

How can I bind the selected value of a cascading dropdown to a h1 tag in Ant Design?

I am using Ant Design to create a cascading dropdown. I am looking to return the selected value as a tag to display something like "You selected {name}". How can I bind the selected value to the h1 tag? Here is the code so far:
const options = [
{
value: 'Person',
label: 'person',
children: [
{
value: 'amy',
label: 'Amy',
},
{
value: 'john',
label: 'John'
}
],
}
];
function onChange(value, selectedOptions) {
console.log(value, selectedOptions);
}
function filter(inputValue, path) {
return path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
}
class CascadingDropdown extends Component{
render(){
return(
<div>
<p>Please select a person:</p>
<div>
<Cascader
options={options}
onChange={onChange}
placeholder="Please select"
showSearch={{ filter }}
onSearch={value => console.log(value)}
/>
</div>
<h1>You selected {name}</h1> // here is where I want to print the name
</div>
);
}
}
export default CascadingDropdown;
Use can use state to display the selected value as shown in the following code
const options = [
{
value: 'Person',
label: 'person',
children: [
{
value: 'amy',
label: 'Amy',
},
{
value: 'john',
label: 'John',
},
],
},
];
class CascadingDropdown extends Component {
onChange(value, selectedOptions) {
console.log(value, selectedOptions);
if (value != undefined) {
this.setState({ name: value[1].toString() });
}
}
filter(inputValue, path) {
return path.some(
(option) =>
option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1
);
}
constructor(props) {
super(props);
this.state = {
name: '',
};
}
render() {
return (
<div>
<p>Please select a person:</p>
<div>
<Cascader
options={options}
onChange={this.onChange.bind(this)}
placeholder="Please select"
showSearch={this.filter}
onSearch={(value) => console.log(value)}
/>
</div>
<h1>You selected {this.state.name}</h1>
</div>
);
}
}
Screenshot:

How to prevent rows adjustment after they are expanded?

I am working with antd table and antd transfer component and I am facing a small challenge with CSS.
I have created a small example with codesandbox. If I try to expand a row, you will see that other columns try to adjust themselves. Is there a way I could prevent this? I do not want the rows to adjust themselves. The table should feel the same after the expansion as it was before the expansion.
This is code from the sandbox link I shared above that generates the table.
import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Transfer, Table, Tag } from "antd";
function difference(listOne, listTwo) {
const set1 = new Set(listOne);
const set2 = new Set(listTwo);
const difference = new Set([...set1].filter(x => !set2.has(x)));
return Array.from(difference);
}
// Customize Table Transfer
const TableTransfer = ({ leftColumns, rightColumns, ...restProps }) => (
<Transfer {...restProps}>
{({
direction,
filteredItems,
onItemSelectAll,
onItemSelect,
selectedKeys: listSelectedKeys,
disabled: listDisabled
}) => {
const columns = direction === "left" ? leftColumns : rightColumns;
const rowSelection = {
getCheckboxProps: item => ({ disabled: listDisabled || item.disabled }),
onSelectAll(selected, selectedRows) {
const treeSelectedKeys = selectedRows
.filter(item => !item.disabled)
.map(({ key }) => key);
const diffKeys = selected
? difference(treeSelectedKeys, listSelectedKeys)
: difference(listSelectedKeys, treeSelectedKeys);
onItemSelectAll(diffKeys, selected);
},
onSelect({ key }, selected) {
onItemSelect(key, selected);
},
selectedRowKeys: listSelectedKeys
};
return (
<Table
rowSelection={rowSelection}
columns={columns}
dataSource={filteredItems}
size="small"
/>
);
}}
</Transfer>
);
const mockTags = ["eg", "gg", "e"];
const mockData = [];
for (let i = 0; i < 20; i++) {
let data = {
key: i.toString(),
title: `eq${i + 1}`,
description: `description of eq${i + 1}`,
disabled: false, //i % 4 === 0,
tag: mockTags[i % 3]
};
if (i % 2 === 0) {
const children = [
{
key: i.toString() + "children",
title: `children-${i + 1}`,
description: `children description-${i + 1}`,
disabled: true,
tag: "tag"
}
];
data["children"] = children;
}
mockData.push(data);
}
const originTargetKeys = mockData
.filter(item => +item.key % 3 > 1)
.map(item => item.key);
const leftTableColumns = [
{
dataIndex: "title",
title: "Name"
},
{
dataIndex: "tag",
title: "Tag",
render: tag => <Tag>{tag}</Tag>
},
{
dataIndex: "description",
title: "Description"
}
];
const rightTableColumns = [
{
dataIndex: "title",
title: "Names"
},
{
dataIndex: "tag",
title: "Tag",
render: tag => <Tag>{tag}</Tag>
},
{
dataIndex: "description",
title: "Description"
}
];
class App extends React.Component {
state = {
targetKeys: originTargetKeys
};
onChange = nextTargetKeys => {
this.setState({ targetKeys: nextTargetKeys });
};
render() {
const { targetKeys, disabled } = this.state;
return (
<div>
<TableTransfer
className="table-transfer"
dataSource={mockData}
titles={[
<div>
<input type="checkbox" checked />
Equipment <input type="checkbox" checked /> Groups
</div>,
<div>
<input type="checkbox" checked />
Equipment <input type="checkbox" checked /> Groups
</div>
]}
targetKeys={targetKeys}
disabled={disabled}
showSearch={true}
onChange={this.onChange}
filterOption={(inputValue, item) =>
item.title.indexOf(inputValue) !== -1 ||
item.tag.indexOf(inputValue) !== -1
}
leftColumns={leftTableColumns}
rightColumns={rightTableColumns}
locale={{
itemUnit: "Equipment",
itemsUnit: "Equipments",
notFoundContent: "The list is empty",
searchPlaceholder: "Search here"
}}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));
You want to constraint your columns width, for example, try this on the leftTableColumns and notice the difference with the right one:
const leftTableColumns = [
{
dataIndex: 'title',
title: 'Name',
width: '45%'
},
{
dataIndex: 'tag',
title: 'Tag',
render: tag => <Tag>{tag}</Tag>,
width: '10%'
},
{
dataIndex: 'description',
title: 'Description',
width: '40%'
}
];
Refer to Table Column API.
Fork of your codebox:

How can I store the selected semantic UI dropdown option in state?

I have a dropdown list with 5 options. I need to save the selected option to my state as listValue.
My list of options and the state
const options = [
{ key: 1, text: 'OK', value: 1 },
{ key: 2, text: 'Avvikelse', value: 2 },
{ key: 3, text: 'Ej Relevant', value: 3 },
{ key: 4, text: 'Observation', value: 4 },
{ key: 5, text: 'Saknas', value: 5 },
]
export default class ConfirmationModal extends React.Component {
state = {
listValue: 'Status'
}
My list (from semantic-ui)
dropDownList = () => (
<Dropdown
placeholder={this.state.listValue}
clearable
options={options}
selection
/>
)
How can I store the selected option in my state?
You can add an onChange handler and put the value given to the handler in your component state.
Example
const options = [
{ key: 1, text: "OK", value: 1 },
{ key: 2, text: "Avvikelse", value: 2 },
{ key: 3, text: "Ej Relevant", value: 3 },
{ key: 4, text: "Observation", value: 4 },
{ key: 5, text: "Saknas", value: 5 }
];
class DropdownExampleControlled extends React.Component {
state = {
options,
value: options[0].value
};
handleChange = (_e, { value }) => this.setState({ value });
render() {
const { value, options } = this.state;
const currentOption = options.find(o => o.value === value);
return (
<Grid columns={2}>
<Grid.Column>
<Dropdown
onChange={this.handleChange}
options={options}
placeholder="Choose an option"
selection
value={value}
/>
</Grid.Column>
<Grid.Column>
<Segment secondary>
<pre>Current value: {currentOption.text}</pre>
</Segment>
</Grid.Column>
</Grid>
);
}
}
As I understood you, you need to save in the state the values, which user selected?
If yes, You need have an event for example onChange, which means that user seelct that particular option from list. and set it in state
onChange(selectedValue) {
this.setState({listValue: selectedValue});
}
add this function to your component:
handleChange = (_p, { value }) => {
this.setState({ listValue: value});
};
add it as prop to your Dropdown:
<Dropdown onChange={this.handleChange} placeholder={this.state.listValue} clearable options={options} selection />
Handle state management using setState. Simple example:
Example Sandbox
const options = [
{ key: 1, text: 'OK', value: 1 },
{ key: 2, text: 'Avvikelse', value: 2 },
{ key: 3, text: 'Ej Relevant', value: 3 },
{ key: 4, text: 'Observation', value: 4 },
{ key: 5, text: 'Saknas', value: 5 },
]
class App extends Component {
constructor(props){
super(props)
this.state = {
listValue: ''
}
}
componentWillMount() //before render
{
this.setState({
listValue: options[1].text //storing text from second line
})
}
render() {
return (
<div>
{this.state.listValue}
</div>
);
}
}
This displays: Avvikelse

How do I create new option if there are no left while searching in React-Select v2?

I need to create new option with label "Ostatni" while filtering if there are no options left. I tried to do it by customising MenuList and NoOptionsMessage, but nothing works. Is there any way?
NoOptionsMessage = props => (
<components.NoOptionsMessage
{...props}
children={<components.Option {...components.Option.defaultProps} data={{ value: 37, label: 'Ostatni' }} />}
/>
)
You can achieve your goal using filterOption function like the following code:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
hasExtraValue: false,
options: [
{ label: "Label 1", value: 1 },
{ label: "Label 2", value: 2 },
{ label: "Label 3", value: 3 },
{ label: "Label 4", value: 4 },
{ label: "Label 5", value: 5 },
{ label: "Label 6", value: 6 },
{ label: "Label 7", value: 7 },
{ label: "Label 8", value: 8 },
{label: 'Ostatni', value: 'other'}
]
};
}
filterOption = (option, inputValue) => {
// tweak the filterOption to render Ostatni only if there's no other option matching + set hasExtraValue to true in case you want to display an message
if (option.label === "Ostatni"){
const {options} = this.state
const result = options.filter(opt => opt.label.includes(inputValue))
this.setState({ hasExtraValue: !result.length})
return !result.length
};
return option.label.includes(inputValue);
};
render() {
return (
<div>
<Select
isMulti
filterOption={this.filterOption}
noOptionsMessage={() => "No more options"}
options={this.state.options}
/>
// Displays a user friendly message to explain the situation
{this.state.hasExtraValue && <p>Please select 'Ostatni' option if you don't find your option !</p>}
</div>
);
}
}
The idea is to trigger when the user is typing something. If there's no options available you add a new one the desired label to offer the user a new option.
In filterOption you set this special option to be always true so it will always displayed if it exists.
Here a live example.
This now seems possible through a built-in component.
https://react-select.com/creatable
import React, { Component } from 'react';
import CreatableSelect from 'react-select/creatable';
import { colourOptions } from '../data';
export default class CreatableSingle extends Component<*, State> {
handleChange = (newValue: any, actionMeta: any) => {
console.group('Value Changed');
console.log(newValue);
console.log(`action: ${actionMeta.action}`);
console.groupEnd();
};
handleInputChange = (inputValue: any, actionMeta: any) => {
console.group('Input Changed');
console.log(inputValue);
console.log(`action: ${actionMeta.action}`);
console.groupEnd();
};
render() {
return (
<CreatableSelect
isClearable
onChange={this.handleChange}
onInputChange={this.handleInputChange}
options={colourOptions}
/>
);
}
}

Categories