I want to add information detail icon on a form field by which when user hover on i tag or we can say information detail icon then the icon show the details of particular form field
I want that how to implement above in antd form in react
In Ant Design, you can add an information detail icon on a form field using the Tooltip component and the 'InfoCircleOutlined' icon from the #ant-design/icons library.
install npm: npm i #ant-design/icons
Here is an example implementation:
import React from 'react';
import { Form, Input, Tooltip } from 'antd';
import { InfoCircleOutlined } from '#ant-design/icons';
const FormItem = Form.Item;
const BaseForm = () => {
return (
<Form>
<FormItem
name="username"
label={
<span>
Username
<Tooltip title="Enter your username here">
<InfoCircleOutlined />
</Tooltip>
</span>
}
rules={[
{
required: true,
message: 'Please input your username!',
whitespace: true,
},
]}
>
<Input />
</FormItem>
</Form>
);
};
export default BaseForm;
Related
I am working on a login form where each input is created dynamically as a field.
This is my Login.js file:
import _ from 'lodash';
import React, { Component } from 'react';
import {reduxForm, Field } from 'redux-form';
import{ Link } from 'react-router-dom';
import FIELDS from './loginFields';
import LoginField from './LoginField'
import { connect } from 'react-redux';
import * as actions from '../../actions'
class LoginForm extends Component {
constructor(){
super();
this.state={
username: '',
password: ''
};
};
handleChange = (e)=>{
this.setState({username: e.target.value, password: e.target.value});
};
renderFields(){
return _.map(FIELDS, ({ label, name, type })=> {
return <Field onChange={this.handleChange} className='purple-text' key={name} component={ LoginField } type={type} label={label} name={name} />
});
};
render(){
const { username, password } = this.state;
const isEnabled = username.length > 0 && password.lenth>7;
return (
<div className='valign-wrapper row login-box' style={{marginTop:'100px'}}>
<div className='col card hoverable s10 pull-s1 m6 pull-m3 l4 pull-l4'>
<form method='POST' action='/api/login'>
<div className = 'card-content'>
<span className='card-title purple-text' style={{textAlign:'center'}}>Login<a href='/register'> Not a member? sign up!</a></span>
<div className='center-align row'>
<li key='google' style={{marginLeft: '30px'}} className='col m6 center-align white-text darken-3'><a className='white-text' href='/auth/google'><img alt="" src="https://img.icons8.com/cute-clipart/64/000000/google-logo.png"/></a></li>
<li key='facebook' className='col center-align white-text darken-3'><a className='white-text' href='/auth/facebook'><img alt = "" src="https://img.icons8.com/cute-clipart/64/000000/facebook-new.png"/></a></li>
</div>
<div className='row input-field col s12'>
{this.renderFields()}
<Link to='/' className='purple btn-flat left white-text'>Back</Link>
<button disabled={!isEnabled} type='submit' className='purple btn-flat right white-text'>Login
<i className='material-icons right'>done</i>
</button>
</div>
</div>
</form>
</div>
</div>
);
};
};
function validate(values){
const errors = {};
_.each(FIELDS, ({name})=>{
if(!values[name]){
errors[name] = 'You must enter a value!'
}
});
return errors;
};
const form = reduxForm({
validate,
form: 'LoginForm'
});
export default connect(null, actions)(form(LoginForm));
Here is loginFields.js
export default
[
{ label: 'Username', name: 'username', type: 'text'},
{ label: 'Password', name: 'password', type: 'password'}
];
and here is LoginField.js
import React from 'react';
export default ({ input, label, type, meta })=>{
return(
<div>
<label className='purple-text'>{label}</label>
<input {...input} type={type} style= {{marginBottom: '5px'}}/>
<div className = "red-text" style={{ marginBottom: '20px'}}>
{meta.touched && meta.error}
</div>
</div>
);
};
I am having trouble properly setting onChange and my constructor to disable the login button until all fields are filled. I have been able to disable the button until a single input has started to be filled in, not disabled at all, and not enabled at all. but have not been able to achieve the desired outcome.
I have tried using lodash to map over each field grabbing values by the input name property, and moving functions around.
Any help would be greatly appreciated, if i can provide any more information for this question please let me know.
The initial problem I see is the onChange function will update state for both password and username whenever either of them is changed. The function takes the event and does not distinguish as to which input is the target. You can pass an additional parameter from the Field that includes the field name, or you can check the target's id or something so you know which input's state should be updated.
In LoginForm
handleChange = (e, name)=>{
this.setState({[name]: e.target.value});
};
You also need to pass the onChange callback down to the actual input in LoginField.js
import React from 'react';
export default ({ name, label, type, meta, onChange, ...props })=>{
return(
<div>
<label className='purple-text'>{label}</label>
<input onChange={(e) => onChange(e, name)} {...props} type={type} style= {{marginBottom: '5px'}}/>
<div className = "red-text" style={{ marginBottom: '20px'}}>
{meta.touched && meta.error}
</div>
</div>
);
};
Here's a codeSandbox.
just adding this as an answer in case anyone else comes across this issue.
after tons of digging I finally found documentation. in redux form has a built in prop called {invalid} which checks against the validate function. instead of messing with state all i had to do was add
const {invalid} = this.props;
inside the render method. constructor and handle change and onChange were no longer necessary.. then.
<button disabled={invalid}>
I'm using react-calendar package on my react app. Placing <Calendar/> on the file gives the open calendar on the frontend.
But I want to display the calendar if the user clicks the input field:
<div className="form-group">
<label>Start Date</label>
<input type="text"/>
<Calendar style={{display: "none"}} />
</div>
I tried through inline style to hide the calendar component and change on click. But the calendar doesn't hide with inline css also.
Gone through documentation also but didn't find any help.
It will be best you create a wrapper component around your calendar and input. This way it manages its own showCalendar state and can be reused elsewhere.
import React, { useState } from "react";
import Calendar from "react-calendar";
const ReactCalendarDemo = ({ date, setDate }) => {
const [showCalendar, setShowCalendar] = useState(false);
const handleChange = value => {
setDate(value);
setShowCalendar(false);
};
return (
<div>
<input
value={date.toLocaleDateString()}
onFocus={() => setShowCalendar(true)}
/>
<Calendar
className={showCalendar ? "" : "hide"}
value={date}
onChange={handleChange}
/>
</div>
);
};
export default ReactCalendarDemo;
You pass in your current date value and its setter as props.
Then you can toggle display in your CSS style using the hide class
.react-calendar.hide {
display: none;
}
I am working with an antd input field and trying to toggle between the required = true state and required=false state and I noticed a peculiar case where the error message does not go away when input field is no longer required. I am not sure why does not antd handle this situation itself.
Here is what I do:
Input field is initialised as required
I write something and then erase, which gives the message "Please input your username" as shown in the image
Then I click, Click to toggle input field button. This changes the input field state from required = true to required = false.
But the error message remains. How could I have the error message go automatically when the input field is no longer required?
Here is the small demo of the above image I created at codesandbox:
Here is also the code:
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import { Form, Input, Button } from 'antd';
class HorizontalLoginForm extends React.Component {
constructor() {
super();
this.state = {
enable: true
};
this.onButtonClick = this.onButtonClick.bind(this);
}
onButtonClick() {
this.setState({
enable: !this.state.enable
})
}
render() {
const { getFieldDecorator } = this.props.form;
const {enable} = this.state;
return (
<Form layout="inline">
<Form.Item>
{getFieldDecorator('username', {
rules: [{ required: this.state.enable, message: 'Please input your username!' }],
})(
<Input disabled = {!enable}
/>,
)}
</Form.Item>
<Form.Item>
<Button type="primary" onClick={this.onButtonClick}>
Click to toggle input field
</Button>
</Form.Item>
</Form>
);
}
}
const WrappedHorizontalLoginForm = Form.create({ name: 'horizontal_login' })(HorizontalLoginForm);
ReactDOM.render(<WrappedHorizontalLoginForm />, document.getElementById('container'));
It looks like there is no way to achieve this kind of behaviour as the Form.Item sets new validation state only on onInput call (when you enter something into Input inside) and therefore it doesn't take the 'required' switch into account.
In case if you need to change the validation behaviour you can go around with a simple solution like:
{enable ?
(<Form.Item>
{getFieldDecorator('username', {
rules: [{ required: this.state.enable, message: 'Please input your username!' }],
})(
<Input disabled = {!enable}
/>,
)}
</Form.Item>) :
<Form.Item>
<Input disabled = {!enable} />
</Form.Item>`}
The only caveat of this solution is that it will hide the previously entered value on change of the 'enable' switch but you can save them anywhere in your state and then assign the default input value to the value of this 'state entered value'
I am trying to autofill textfield using setState when user click on edit button. Text is set but default hintText and floatingLabelText overlap with text. When i click inside textfield lable go up but hintText overlap with text. How can i solve this?
this is textfield overlap image.
this is button
<button type="button" className="btn btn-primary btn-sm" id="edit"
onClick={this.editProduct.bind(this, product)} value="edit">Edit</button>
when user click on edit button editProduct function setState is set like this
editProduct = product => {
this.setState({
name: product.name,
brand: product.brand,
description: product.description,
});
}
render() {
const { name, brand, description } = this.state;
const values = { name, brand, description };
return (
<div class="container">
<Addproduct
handleChange={this.handleChange}
values={values}
/>
)
}
this is textfield inside Addproduct component
<TextField
hintText="Enter Your Product Name"
floatingLabelText="Product Name"
onChange={handleChange('name')}
errorText={values.nameError}
defaultValue={values.name}
fullWidth
/>
You can check against the value and put '' empty string if no input there like this answer:
React Material UI Label Overlaps with Text
<TextField
hintText="Enter Your Product Name"
floatingLabelText="Product Name"
onChange={handleChange('name')}
errorText={values.nameError}
defaultValue={values.name}
value={values.name || ''}
fullWidth
/>
If you don't need defaultValue just remove it
I faced the same issue, but when I changed my functional component to class component it worked. Not sure what was the reason but it worked. I'm still looking for the reason, I'll update in this thread once I find. But you can give it a try and check if that works.
You need to change the Textfield attributes to
<TextField
placeholder="Enter Your Product Name"
label="Product Name"
onChange={handleChange('name')}
errorText={values.nameError}
value={values.name}
fullWidth
/>
i am developing a form in reactjs using formik plugin plugin link. when i submit form i am getting text fields values but dropdown values are coming empty...
this is my dropdown select
<div className="form-group">
<Field component="select" id="category" name="category" value={this.state.value} className={"form-control"} onChange={ this.handleChange }>
<option value="lokaler">Lokaler</option>
<option value="jobb">Jobb</option>
<option value="saker-ting">Saker & ting</option>
<option value="evenemang">Evenemang</option>
</Field>
</div>
handle submit function
export default withFormik({
enableReinitialize: true,
mapPropsToValues({ category }) {
return {
category: category || ''
}
},
handleSubmit(values, { setStatus, setErrors }){
console.log("data is this: ");
console.log(values); //here i am getting all form fields values except select value returning empty value
console.log("category: "+values.category);// here i always get empty value but not getting selected value
}
i am getting all text fields values in handle submit function but i am not able to get dropdown selected value....kindly tell me how to get dropdown select value in handle submit function ?
I also faced this problem yesterday. My problem was to submit form that contains ant design dropdown. I finally make it work after hours of:
revisiting the Formik Docs
watch Andrew Mead's video Better React Form with Formik again.
also viewing Jared Palmer's Working with 3rd-party inputs #1: react-select
The doc said you need to set onChange, onBlur events to setFieldValue, setFieldTouched props respectively like 3rd-party input example:
<MySelect
value={values.topics}
onChange={setFieldValue}
onBlur={setFieldTouched}
error={errors.topics}
touched={touched.topics}
/>
So to my problem, I need to change a bit:
<Select
{...field}
onChange={(value) => setFieldValue('fruitName', value)}
onBlur={()=> setFieldTouched('fruitName', true)}
value={values.fruitName}
...
>
...
</Select>
Hope this will help.
Here is my CodeSandbox
A more robust way to handle select components whilst using Formik would be to also use Jed Watsons react-select component. The two work together nicely and abstract away a lot of the boilerplate you would normally need to implement to get the component working seamlessly with Formik.
I have forked a simple example from Jared Palmer's react-select / Formik example on codesandbox and adjusted it to reflect your code above.
import "./formik-demo.css";
import React from "react";
import { render } from "react-dom";
import { withFormik } from "formik";
import Select from "react-select";
import "react-select/dist/react-select.css";
const options = [
{ value: "lokaler", label: "Lokaler" },
{ value: "jobb", label: "Jobb" },
{ value: "saker-ting", label: "Saker & ting" },
{ value: "evenemang", label: "Evenemang" }
];
const MyForm = props => {
const {
values,
handleChange,
handleBlur,
handleSubmit,
setFieldValue
} = props;
return (
<form onSubmit={handleSubmit}>
<label htmlFor="myText" style={{ display: "block" }}>
My Text Field
</label>
<input
id="myText"
placeholder="Enter some text"
value={values.myText}
onChange={handleChange}
onBlur={handleBlur}
/>
<MySelect value={values.option} onChange={setFieldValue} />
<button type="submit">Submit</button>
</form>
);
};
class MySelect extends React.Component {
handleChange = value => {
// this is going to call setFieldValue and manually update values.topcis
this.props.onChange("option", value);
};
render() {
return (
<div style={{ margin: "1rem 0" }}>
<label htmlFor="color">Select an Option </label>
<Select
id="color"
options={options}
onChange={this.handleChange}
value={this.props.value}
/>
</div>
);
}
}
const MyEnhancedForm = withFormik({
mapPropsToValues: props => ({
myText: "",
option: {}
}),
handleSubmit: (values, { setSubmitting }) => {
console.log(values);
}
})(MyForm);
const App = () => <MyEnhancedForm />;
render(<App />, document.getElementById("root"));
There are a few gotchas, you have to include the react select css for the component to display properly
import "react-select/dist/react-select.css";
the function mapPropsToValues option field should be initialised to an object
mapPropsToValues: props => ({
myText: "",
option: {}
Finally here is a link to the codesandbox example