Way to clear selection in React Select - javascript

is there a way to clear the selected value in the react select dropdown menu after choosing an option with a press of a clear button? Thank you.
import Select from 'react-select';
const TransactionDetailsPanel = props => {
const clearQuery = () => {
inputRef.current.value=null;
};
return (
<>
<div className="columns is-gapless is-marginless">
<Select className="column is-3" options={options} onChange={updateSelection}
ref={selectRef} placeholder="Advanced Detail Search" />
<input className="column is-3" type="text"
ref={inputRef} placeholder="Enter query here..."/>
<div className="buttons">
<button className="button" onClick={updateQuery}>Details Search</button>
<button className="button" onClick={clearQuery}>Clear</button>
</div>
</div>

Related

I want to get selected value from select options on button click in react.js

I want to get the selected value from the dropdown on button click and then I want to save it in the firebase database. Everything is working fine except dropdown. I also want to add a dropdown value in the firebase database. Anyone can help me how can I get it? I'm trying but it is giving error. Anyone can help me?
import React, { Component } from 'react';
import Select from 'react-select';
import firebase from '../config/firebase.js';
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' },
];
class PostAd extends React.Component {
constructor() {
super();
this.state = {
selectedOption: null,
ads: [],
};
}
handleClick = () => {
firebase.database().ref('/').child('ads').push(this.state);
console.log(`Option selected:`, selectedOption);
};
handleChange = (e) => {
this.setState({
selectedOption,
[e.target.name]: e.target.value,
});
console.log(`Option selected:`, selectedOption);
};
render() {
const { selectedOption } = this.state;
return (
<div className="container postAd-container">
<h6 className="p-3">CHOOSE A CATEGORY</h6>
<hr />
<Select value={selectedOption} onChange={this.handleChange} options={options} />
<div className="p-3">
<div className="">
<p>Condition *</p>
<button className="btn-attributes" name="new" value="new" onClick={this.handleChange}>
New
</button>
<button className="btn-attributes" name="used" value="used" onClick={this.handleChange}>
Used
</button>
</div>
<div className="pt-2">
<p>Type *</p>
<button className="btn-attributes">Apple</button>
<button className="btn-attributes">Dany Tabs</button>
<button className="btn-attributes">Q Tabs</button>
<button className="btn-attributes">Samsung</button>
<button className="btn-attributes">Other Tablets</button>
</div>
<div className="pt-5">
<p>Ad Title *</p>
<div className="form-group row">
<div className="col-sm-6">
<input
type="email"
name="adTitle"
onChange={this.handleChange}
className="form-control form-control-lg"
/>
<p className="font-11">Mention the key features of your item (e.g. brand, model, age, type) 0 / 70</p>
</div>
</div>
</div>
<div className="pt-5">
<p>Description *</p>
<div className="form-group row">
<div className="col-sm-6">
<textarea name="description" onChange={this.handleChange} className="form-control" rows="3"></textarea>
<p className="font-11">Include condition, features and reason for selling 0 / 4096</p>
</div>
</div>
</div>
</div>
<hr />
<div className="p-4">
<div className="">
<h6>SET A PRICE</h6>
<div className="form-group row">
<div className="col-sm-6">
<div className="input-group mb-2">
<div className="input-group-prepend">
<div className="input-group-text">Rs</div>
</div>
<input type="number" name="price" onChange={this.handleChange} className="form-control" />
</div>
</div>
</div>
</div>
</div>
<div className="form-row pb-3">
<div className="col-md-12 text-center">
<button type="submit" className="btn btn-primary" onClick={this.handleClick}>
Post Ad
</button>
</div>
</div>
</div>
);
}
}
export default PostAd;
Make a seperate function this.handleClickButton and use it for New and Used buttons. instead this.handleChange
handleClickButton = e => {
this.setState({
[e.target.name]: e.target.value
});
};
handleChange = selectedOption => {
this.setState({
selectedOption
},() => {
console.log(`Option selected:`, this.state.selectedOption);
});
};
This code will change the dropdown without any error.
If you would like to manage both with the same function. Following is the solution:
handleChange = selectedOption => {
//onClick it will get e.target.value
if (e.target.value) {
this.setState({
[e.target.name]: e.target.value
});
} else {
//onChange it will get the selected option.
this.setState({
selectedOption: e
});
}
};

i want to disabled button if textbox null in react

return (
{jobstate.jobs.map((data,i) =>{
<form>
<input type="text" placeholder="Post a comment" onChange={(e) => jobcmthandler(e,data._id,i) } />
<button type="button" onClick={postcmt} >Send</button>
</form>
})}
)
I generate dynamic HTML using the map function and I want to disabled button if text null for induvial form and also how to get text value on button click in react js
I can't really see why you'd want to do this but here you go (example):
import React, { useState } from "react";
export default function App() {
return ["Name", "Age"].map((label) => <Form label={label} />);
}
function Form({ label }) {
const [readValue, writeValue] = useState("");
return (
<form>
<label>{label}</label>
<input
type="text"
placeholder="Post a comment"
onChange={(e) => writeValue(e.target.value)}
value={readValue}
/>
<button
type="button"
onClick={() => console.log("Submit")}
disabled={readValue === ""}
>
Send
</button>
</form>
);
}

How to write inside input after making it editable?

I Am populating values of my input field from JSON data what am getting from back-end, now there is an edit button on UI by on click on that button I am enabling my input field but not able to type inside as I am setting some value
I want to write inside the input once I have made them editable.
const { register, handleSubmit, errors } = useForm();
const [disabled, setdisabled] = useState(false);
const [editBtn, seteditBtn] = useState(true);
<form onSubmit={handleSubmit(onSubmit)}>
{editBtn === true && (
<div align="right">
<button
className="btn white_color_btn"
type="button"
onClick={edit}
>
Edit
</button>
</div>
)}
{editBtn === false && (
<button className="btn white_color_btn" type="submit">
Save
</button>
)}
<div className="row">
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
disable
id="firstName"
name="firstName"
value={dataItems.firstname}
disabled={disabled ? "" : "disabled"}
ref={register({ required: true })}
/>
{errors.firstname && (
<span className="text-danger">first name required</span>
)}
<br />
<label htmlFor="emp_designation">First name</label>
</div>
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
disabled
id="lastname"
name="lastname"
value={dataItems.lastname}
disabled={disabled ? "" : "disabled"}
ref={register({ required: true })}
/>
{errors.lastname && (
<span className="text-danger">last name required</span>
)}
<br />
<label htmlFor="lastname">Lastname</label>
</div>
</div>
</form>
On click of edit
const edit = () => {
setdisabled(true);
};
Code sandbox
You need to make your input as a controlled component and write onChange handlers which will update the state. This will allow you to edit the input field values. Demo
const [disabled, setdisabled] = useState(false);
const [name, setName] = useState(empData.item.name) // setting default name
const [lastname, setLastname] = useState(empData.item.lastname) // default lastname
const edit = () => {
setdisabled(true);
};
return (<div className="container-fluid">
<div align="right">
<button className="btn" onClick={edit}>
Edit
</button>
</div>
<div className="row">
<div>
<input
type="text"
disable
id="item.value"
value={name}
onChange={(e) => {
setName(e.target.value)
}}
disabled={disabled ? "" : "disabled"}
/>
<br />
<label htmlFor="name">Name</label>
</div>
<div>
<input
type="text"
disabled
id={"lastname"}
value={lastname}
onChange={(e) => {
setLastname(e.target.value)
}}
disabled={disabled ? "" : "disabled"}
/>
<br />
<label htmlFor="lastname">Lastname</label>
</div>
</div>
</div>);
Your input is controlled by the value you are giving to it. ie: Its value is always for example empData.item.name.
And you are not providing a change handler to handle the change.
Try adding something like this:
function myChangeHandler(e){
setEditedValueSomeHow(e.target.value);
}
<input
// ...
onChange={myChangeHandler}
/>
Read more about uncontrolled components
PS: you should have had a warning message in your console like this one:
Edit:
You are using react-hook-form to manage your form but at the same time giving values to your inputs.
Please refer to this link to initialize your form values.
short story:
Remove value form your input.
Pass an object to useForm hook containing initial values.
const { register, handleSubmit, errors } = useForm({
defaultValues: {
firstName: "steve",
lastname: "smith"
}
});
Here is a working fork for your codesandbox
In order to make the input editable, you need to update a local state which controlls the input value. As suggested by you in the comments, you are using graphql to get the data, you can make use of useEffect to set the data in state and then on click of edit, update the localState
export default function App() {
const { register, handleSubmit, errors } = useForm();
const [disabled, setdisabled] = useState(true);
const [editBtn, seteditBtn] = useState(true);
const { loading, data } = useQuery("some qraphql query here"); // getting data from graphql
const [formData, setFormData] = useState({});
useEffect(() => {
setFormData(data);
}, [data]);
const edit = () => {
setdisabled(false);
seteditBtn(false);
};
const onSubmit = () => {
console.log(formData);
// submit data using formData state.
};
const handleChange = e => {
const name = e.target.name;
const value = e.target.value;
console.log(name, value);
setFormData(prev => ({ ...prev, [name]: value }));
};
return (
<div className="container-fluid">
<form onSubmit={handleSubmit(onSubmit)}>
{editBtn === true && (
<div align="right">
<button
className="btn white_color_btn"
type="button"
onClick={edit}
>
Edit
</button>
</div>
)}
{editBtn === false && (
<button className="btn white_color_btn" type="submit">
Save
</button>
)}
<div className="row">
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
id="firstname"
name="firstname"
onChange={handleChange}
value={formData.firstname}
disabled={disabled}
ref={register({ required: true })}
/>
{errors.firstname && (
<span className="text-danger">first name required</span>
)}
<br />
<label htmlFor="emp_designation">First name</label>
</div>
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
id="lastname"
name="lastname"
value={formData.lastname}
onChange={handleChange}
disabled={disabled}
ref={register({ required: true })}
/>
{errors.lastname && (
<span className="text-danger">last name required</span>
)}
<br />
<label htmlFor="lastname">Lastname</label>
</div>
</div>
</form>
</div>
);
}
Working mock demo

React useState and map()

I'm trying to make an comment input from map,
but since I use the same useState all the input fields get changed.
How can I target a specific input?
return (
<div>
{posts.map(post => (
<div key={post.id}>
<img
src={`https://localhost:1111/api/posts/uploads/images/${post.content}`}
alt={`${post.id}`}
/>
<p>{post.description}</p>
<span>{post.likes ? post.likes : 0}</span>
<button onClick={() => like(post.id)}>Like</button>
<Link to={`/post/${post.id}`}>Edit</Link>
<button onClick={() => deletePost(post.id)}>Delete</button>
<form onSubmit={uploadComment}>
<input
type="text"
onChange={handleComment}
value={comment}
placeholder="Comment"
/>
</form>
</div>
))}
</div>
)
You have an own state per rendered post, which means that it is a use case for an own component:
function Post(post, deletePost) {
const [comment, setComment] = useState('');
const uploadComment = () => {}; // your code is missing
return (
<div key={post.id}>
<img
src={`https://localhost:1111/api/posts/uploads/images/${post.content}`}
alt={`${post.id}`}
/>
<p>{post.description}</p>
<span>{post.likes ? post.likes : 0}</span>
<button onClick={() => like(post.id)}>Like</button>
<Link to={`/post/${post.id}`}>Edit</Link>
<button onClick={() => deletePost(post.id)}>Delete</button>
<form onSubmit={uploadComment}>
<input
type="text"
onChange={e => setComment(e.target.value)}
value={comment}
placeholder="Comment"
/>
</form>
</div>
)
}
Then your render function would look like this:
return (
<div>
{posts.map(post => <Post post={post} deletePost={deletePost} />)}
</div>
)
Consider using react useState hook per input.

Render array of inputs in react

I have an array of emails (as a part of a bigger model). These are displayed in seperate rows witha remove button for each (the address itself can be updated in the input box directly). Unfortunately I dont know how to do this in react when the inputs are renderd using a map function.
(I am converting a meteor blaze project to meteor react).
Everything renders but how do I attach to change event so I can update my array of emails? onChange + value need to be set somehow.
This is the map function
return this.data.emailGroup.emails.map((email) => {
return (
<div key={email} className="input-group">
<input type="text" className="form-control" onChange={self.handleEmailListChange} value={email}/>
<div className="input-group-btn">
<button type="button"
className="btn btn-default remove-email"><span
className="glyphicon glyphicon-remove"></span></button>
</div>
</div>
);
});
The initial state(which is populated with data from the db:
getInitialState() {
return {
name : '',
description: '',
emails : [],
newEmailAddress : ''
}
},
Upon request here is the render method(it requires a getContent method.The getcontent method is there because in meteor I need to wait for data so in the meantime I need a loading state.
getContent() {
return (
<div className="box box-success">
<div className="box-header with-border">
<h3 className="box-title">List of emails</h3>
</div>
<form role="form" className="form-horizontal">
<div className="box-body">
<p>Below is a list of email addresses which are added to this email group. If
you
want
to add more
you can add them one by one by inputting in the box below or add a list into
the
same box (email
addresses have to be seperated by either a space or ;) then press Add to add
to
the
list. You can edit
the addresses directly as well as remove them.</p>
<div className="input-group">
<input type="text" className="form-control"
value={this.state.newEmailAddress}
onChange={this.handleAddNewEmail}
placeholder="Email addresses seperated by a space or a semicolon ; i.e. test1#test.se;test2#test.se"/>
<span className="input-group-btn">
<button type="button" onClick={this.handleAddNewEmailButton} className="btn btn-info btn-flat add-email">Add</button>
</span>
</div>
<br/>
{this.renderEmail()}
</div>
</form>
</div>
)
},
render()
{
var contentStyle = {
minHeight : '946px'
};
return (
<div className="content-wrapper" style={contentStyle}>
<section className="content-header">
<h1>
{this.data.emailGroup? this.data.emailGroup.name : 'hello'}
</h1>
<small> Created by: Christian Klinton</small>
<br/>
<small> Last updated by: Christian Klinton - 2015-11-12 08:10:11</small>
<ol className="breadcrumb">
<li><i className="fa fa-dashboard"></i> Home</li>
<li>Email groups</li>
<li className="active">{this.data.emailGroup? this.data.emailGroup.name : 'loading'}</li>
</ol>
</section>
<section className="content">
<div className="row">
<div className="col-md-6">
<div className="box box-primary">
<div className="box-header with-border">
<h3 className="box-title">Information</h3>
</div>
<form role="form">
<div className="box-body">
<div className="form-group">
<label htmlFor="inputName">Name</label>
<input type="email" className="form-control" id="name"
onChange={this.handleNameChange}
placeholder="Set the name of the email group" autoComplete="off"
value={this.state.name}/>
</div>
<div className="form-group">
<label>Description</label>
<textarea className="form-control" rows="3" id="description"
placeholder="Enter a description what and how the template is used..."
onChange={this.handleDesriptionChange}
value={this.state.description}
></textarea>
</div>
</div>
</form>
</div>
</div>
<div className="col-md-6">
{this.data.emailGroup? this.getContent() : <p>Loading</p> }
</div>
<div className="form-group">
<div className="col-sm-offset-8 col-sm-4">
<div className="pull-right">
<button className="btn btn-primary">Delete all</button>
<button className="btn btn-primary save">Save</button>
</div>
</div>
</div>
</div>
</section>
</div>
)
}
React requires you to have something unique for every element in the rendered array, it's called a key, and it's an attribute.
If you don't know what to assign to the key, just assign it the array's indexes:
this.props.doors.map((door, index) => (
<div key={index} className="door"></div>
));
Here's the same solution applied to your problem:
return this.data.emailGroup.emails.map((email, index) => {
return (
<div key={index} className="input-group">
<input type="text"
className="form-control"
onChange={self.handleEmailListChange.bind(this, index)} value={email}/>
</div>
);
});
Notice how I bound handleEmailListChange to receive the index of the modified email. If handleEmailListChange accepts an index, it can update the modified email within the state:
handleEmailListChange: function(index, event) {
var emails = this.state.emails.slice(); // Make a copy of the emails first.
emails[index] = event.target.value; // Update it with the modified email.
this.setState({emails: emails}); // Update the state.
}
I believe what you're looking for is something like this:
MyPage = React.createClass({
mixins: [ReactMeteorData],
getMeteorData() {
// ...
},
render() {
const emails = this.data.emailGroup.emails.map((email) => {
return (
<div key={email} className="input-group">
<input type="text" className="form-control"
onChange={this.handleEmailListChange} value={email} />
<div className="input-group-btn">
<button type="button"
className="btn btn-default remove-email"><span
className="glyphicon glyphicon-remove" /></button>
</div>
</div>
);
});
return <div>
{emails}
</div>
}
});
I changed self to this. Since you're using the ES6 arrow function, there's no need to assign self = this.
You should place your Array.map directly inside your render() function. Just take care that each array element is wrapped inside a parent element (<div> here) and must have a unique key={}
class ArrayMap extends React.Component{
//your functions
handleEmailChanged(key){
// Handle email
}
render(){
return(
<div>
{
this.data.emailGroup.emails.map((email) => {
<div key={email.key}>
<button onClick={this.handleEmailChanged.bind(this,email.key)}/>
</div>
});
}
</div>
);
}
}

Categories