Use Popup to display Input Error message in React-Semantic-UI - reactjs

It is possible to use the Popup Component to display the Input Errors in react Semantic UI?
Something like this
<Popup
content="Error Message"
trigger={
<Input placeholder='Name' />
}
/>

I think there is a way to achieve that, but not by using the PopUp component. To achieve that see the semantic-ui-react documentation on Forms with Label (pointing).
You can use the logic illustrated in the code below:
import React, { Component } from 'react'
import { Form, Label, Input, Button } from 'semantic-ui-react'
export default class MyCustomForm extends Component {
constructor(props){
super(props)
}
this.state = {
input1: 'some value',
input2: '',
errors: {
input1: 'Input 1 error message'
}
this.onChange = this.onChange.bind(this)
this.validate = this.validate.bind(this)
this.onSubmit = this.onSubmit.bind(this)
}
onChange(e, {name, value}){
const state = this.state
const { errors } = state
if(errors[name]){
delete errors[name]
}
this.setState(Object.assign({},...state,{[name]: value, errors }))
this.validate(name, value)
}
validate(name, value){
{/*
THIS SHOULD VALIDATE THE INPUT WITH THE APPROPRIATE NAME ATTRIBUTE
AND UPDATE THE ERRORS ATTRIBUTE OF THE STATE
*/}
}
onSubmit(e){
e.preventDefault()
{/* CLEAR THE ERRORS OF THE STATE, SUBMIT FORM TO BACKEND, THENj RESET ERRORS IF ANY */}
}
render() {
<Form size='small' key='mycustomform'>
<Form.Group>
<Form.Field error={errors.input1} required>
<label>Input1</label>
<Input name='input1' onChange={this.onChange}/>
{errors.input1 && <Label pointing color='red'>{errors.input1}</Label>}
</Form.Field>
</Form.Group>
<Form.Group>
<Form.Field error={errors.input2}>
<label>Input2</label>
<Input name='input2' onChange={this.onChange}/>
{errors.input2 && <Label pointing color='red'>{errors.input2}</Label>}
</Form.Field>
</Form.Group>
<Form.Field control={Button} onSubmit={this.onSubmit}/>
</Form>
}

Related

Keep getting max update exceeded error but cannot seem to find error in code

I have made forms like this before but I seem to be missing something in this one. I keep getting the error "maximum update depth exceeded error" but I dont see where I am goin wrong and I've spent too much time looking at it. I already tried to change my onChange to include an arrow because others have suggested to do so , but when that happens I cant type in the input boxes. like so
onChange={()=>this.handleChange("username")}
I should note that I only get the error when I try to register the user and not when I type into the input. Here is the full error as well.
at checkForNestedUpdates (react-dom.development.js:23804)
at scheduleUpdateOnFiber (react-dom.development.js:21836)
at Object.enqueueSetState (react-dom.development.js:12468)
at Router.Component.setState (react.development.js:366)
at react-router.js:75
at listener (history.js:156)
at history.js:174
at Array.forEach (<anonymous>)
at Object.notifyListeners (history.js:173)
at setState (history.js:562)
Here is my code, please help.
import React from "React"
class Splash extends React.Component{
constructor(props) {
super(props)
this.state = this.props.user;
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
this.props.clearErrors();
}
handleSubmit(event) {
event.preventDefault();
this.props.signUp(this.state);
}
handleChange(field) {
return (e) => {
this.setState({ [field]: e.currentTarget.value })
};
}
render() {
return (
<div className="splash-background">
<div className="modal-screeen">
<form className="modal" onSubmit={this.handleSubmit}>
<h2 className="welcom-text"></h2>
<input className="user-input" type="text" placeholder="Name" onChange={this.handleChange("name")} value={this.state.name}/>
<input className="user-input" type="text" placeholder="Email" onChange={this.handleChange("email")} value={this.state.email}/>
<input className="user-input" type="text" placeholder="Create Username" onChange={this.handleChange("username")} value={this.state.username}/>
<input className="user-input" type="password" placeholder="Create Password" onChange={this.handleChange("password")} value={this.state.password}/>
<button>Sign Up</button>
</form>
</div>
</div>
);
}
}
export default Splash
import { connect } from "react-redux";
import { signup, login, clearErrors } from "../../actions/session_actions.js";
import Splash from "./splash";
const mapStateToProps = ({ errors }) => {
return {
errors: errors.session,
user: {
username: "",
password: "",
name:"",
email: "",
},
};
};
const mapDispatchToProps = (dispatch) => {
return {
signUp: (user) => dispatch(signup(user)),
login: (user) => dispatch(login(user)),
clearErrors: () => dispatch(clearErrors()),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Splash);
I believe the problem here is the implementation of redux and react state. If you're using redux to manage the form state then I don't think there is a need to also manage that same state with react.
Try something like this, but keep in mind this code isn't tested.
class Splash extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
this.props.clearErrors();
}
handleSubmit(event) {
event.preventDefault();
this.props.signUp(this.props.user);
}
handleChange(e) {
// here you would have another action to update redux state depending
// on which input has changed. You can grab the input name via e.target.name
}
render() {
return (
<div className="splash-background">
<div className="modal-screeen">
<form className="modal" onSubmit={this.handleSubmit}>
<h2 className="welcom-text"></h2>
<input
className="user-input"
type="text"
placeholder="Name"
name="name"
onChange={this.handleChange}
value={this.props.user.name}
/>
<input
className="user-input"
type="text"
placeholder="Email"
name="email"
onChange={this.handleChange}
value={this.props.user.email}
/>
<input
className="user-input"
type="text"
placeholder="Create Username"
name="username"
onChange={this.handleChange}
value={this.props.user.username}
/>
<input
className="user-input"
type="password"
placeholder="Create Password"
name="password"
onChange={this.handleChange}
value={this.props.user.password}
/>
<button>Sign Up</button>
</form>
</div>
</div>
);
}
}
export default Splash;
When it comes to form data, I find it's easier to manage just with react state. Generally redux is used to manage state that is shared across the whole application/multiple components.
The problem was actually in my route util file. I had an infinite loop of rerouting!

Validation and isValid issues facing with Formik in react js

I am using formik in react js.. currently I just added enableReinitialize to update the initialValues after there is any change in state.. so here the validation message are shown even after the correcting the text. This validation message get's removed after clicking outside of textbox. can I hide this message as soon as the the data is corrected in textbox.
Dirty and isValid keeps the button disabled even though there are no validations.
Register.JS
import React, { Component, useState } from 'react';
import {Formik} from 'formik';
import validateSignUp from '../../containers/Validations/SignUp/SignUpValidation'
class Register extends Component {
constructor(props) {
super();
this.state = {
fields: {CountryCode:'', EmailId:'', Password:''},
errors: {},
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
let fields = this.state.fields;
fields[e.target.name] = e.target.value;
this.setState({
fields,
});
}
handleSubmit(){
console.log(this.state.fields);
}
render() {
return (
<Formik
enableReinitialize
initialValues={this.state.fields}
validate={validateSignUp}
>
{({errors, touched, handleBlur, isSubmitting, isValid, dirty}) => (
<div className='signUp-form form_wrapper'>
<div className='form-body'>
<form name='first' onSubmit={this.handleSubmit}>
<div className='row'></div>
<div className='form-group'>
<label>Email address</label>
<input type='email' name="EmailId"
onChange={this.handleChange} placeholder='abc#example.com'
onBlur={handleBlur} value={this.state.fields.EmailId}
className='form-control'/>
<div className='info-message'>
<div className='errorMsg'>{errors.EmailId &&
touched.EmailId && errors.EmailId}</div>
</div>
</div>
<div className='form-group'>
<label>Password</label>
<input type='password' name="Password"
onChange={this.handleChange} onBlur={handleBlur} value={this.state.fields.Password}
className='form-control'/>
<div className='info-message'>
<div className='errorMsg'>{errors.Password &&
touched.Password && errors.Password}</div>
</div>
</div>
<button type='submit' disabled={!(isValid && dirty)} className='btn btn-danger'>
continue
</button>
</form>
</div>
</div>
)}
</Formik>
);
}
}
export default Register;
SignUpValidation.JS
const validateSignUp = validate => {
const errors = {};
if (!validate.EmailId) {
errors.EmailId = 'Please Enter Email ID';
} else if (!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(validate.EmailId)) {
errors.EmailId = 'Invalid email address';
}
if (!validate.Password) {
errors.Password = 'Please Enter New Password Which you want to set';
} else if (!validate.Password.match(/^.*(?=.{8,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*
[##$%&]).*$/)) {
errors.Password = 'Password Must contain at least one number and one uppercase and lowercase
letter, and at least 8 or more characters';
}
return errors;
};
export default validateSignUp;
I think you should use yup for formik validations as it automatically handle those cases.

react-bootstrap - Form.Control defaultValue not updated when re-rendered

When I call setState and my form is re-rendered, the value of the text input doesn't change.
import React, { Component } from 'react';
import { Button, Col, Form, Row } from 'react-bootstrap';
export default class Test extends Component {
constructor(props) {
super(props);
this.state = {
status: "new"
}
}
approve = (e) => {
this.setState({
status: "I'm newer than you!"
});
e.preventDefault();
}
render() {
return (
<div>
Status is {this.state.status}
<Form onSubmit={this.approve}>
<Form.Group as={Row} controlId="status">
<Form.Label column >Status</Form.Label>
<Col>
<Form.Control readOnly type="text" size="sm" defaultValue={this.state.status} />
</Col>
</Form.Group>
<Form.Group as={Row}>
<Button type="submit">approve</Button>
</Form.Group>
</Form>
</div>
);
}
}
When I click on the button, I see the static text ("Status is ...") get updated but the input field does not. Have I wrongly assumed the text input should update?
If you want to change it, you can replace 'defaultValue' with 'value' in FormControl component.
<Form.Control readOnly type="text" size="sm" value={this.state.status} />

why the page refresh on button click in react?

could you please tell me why the page refresh on button click in react ? I enter something in input field and press button, my page is refresh
I want to get the value of form field
https://codesandbox.io/s/green-frost-414qi
class ContactForm extends React.Component {
handleSubmit = values => {
// print the form values to the console
console.log(values);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text" />
</div>
<button type="submit">Submit</button>
</form>
);
}
}
const ContactRForm = reduxForm({
// a unique name for the form
form: "contact"
})(ContactForm);
export default ContactRForm;
It's standard behavior for forms to refresh the page after submit events. To stop this you can add event.preventDefault()
handleSubmit = event => {
event.preventDefault()
console.log(event.target.firstName.value); //get value from input with name of firstName
};
With Redux-Forms, in order to get the values object and not have the page refresh, we have to use the event-handler that's been created for us by Redux-form. It's created when we pass an onSubmit prop like so to the Form component:
<ContactRForm onSubmit={this.submit} />
Interestingly enough, that handler is now available through the prop handleSubmit(), which I expect has its own event.preventDefault() built in.
Try adding this to your Form component-code:
import React from "react";
import { Field, reduxForm } from "redux-form";
class ContactForm extends React.Component {
render() {
return (
<form onSubmit={this.props.handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text" />
<label htmlFor="lastname">Last Name</label>
<Field name="lastname" component="input" type="text" />
</div>
<button type="submit">Submit</button>
</form>
);
}
}
const ContactRForm = reduxForm({
// a unique name for the form
form: "contact"
})(ContactForm);
export default ContactRForm;
Now the same functionality of the original submit function occurs and the page does not refresh. :)
You can achieve this using below changes.
class ContactForm extends React.Component {
constructor(props){
super(props);
this.state = {
fieldValue : ''
}
this.updateInput = this.updateInput.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
updateInput(event){
this.setState({username : event.target.value})
}
handleSubmit = event=> {
// print the form values to the console
event.preventDefault() // this is used to prevent the form submission
console.log('Your input value is: ' + this.state.username) // your input field value
};
render() {
return (
<form>
<div>
<label htmlFor="firstName">First Name</label>
<Field value={input} onChange={this.updateInput} /> // set the input value
</div>
<button type="submit" onClick={this.handleSubmit} >Submit</button>
</form>
);
}
}
const ContactRForm = reduxForm({
// a unique name for the form
form: "contact"
})(ContactForm);
export default ContactRForm;
This is default behavior of HTML forms to refresh page on submit button. You can stop refresh by adding event.preventDefault();
For more details you can read ReactJS Form documentation
handleSubmit = e => {
event.preventDefault()
// get form value by accessing target values
console.log(e.target.firstName.value);
};

React.Js - FormControl doesn't update my value

I am currently working on the Login side of my react app and I am facing a problem with the update of my state data from the input.
I have this component:
import React from 'react'
import { login } from '../../api/Authentication'
import { setStore } from '../../webapp/storage'
import { Button, ControlLabel, Form, FormControl, FormGroup } from 'react-bootstrap';
export default class LoginPage extends React.Component {
constructor(props){
super(props);
this.state={
email:'',
password:''
}
}
handleSubmit(event) {
if (this.state.email == '' || this.state.password == '') {
if (this.state.email == '') {
this.badInfosAlert('Email field empty')
} else if (this.state.password == '') {
this.badInfosAlert('Password field empty')
}
return
}
console.log('-----------------------')
console.log(this.state.email)
console.log(this.state.password)
var user = {
email: this.state.email,
password: this.state.password
}
console.log(JSON.stringify(user))
console.log('-----------------------')
login(user).then(result => {
if (result != null && result.status == 200) {
setStore('token', result.json.user.token)
} else {
this.badInfosAlert(result.json.error)
}
}).catch(this.badInfosAlert('An error happend'));
}
badInfosAlert(message) {
console.log(message);
alert(message);
}
render() {
return (
<div className='col-lg-12'>
<Form>
<FormGroup controlId="formHorizontalEmail">
<ControlLabel>Email </ControlLabel>
<FormControl type="username" onChange = {(event,newValue) => this.setState({email:newValue})} placeholder="Email" />
</FormGroup>
<FormGroup controlId="formHorizontalPassword">
<ControlLabel>Password </ControlLabel>
<FormControl type="password" onChange = {(event,newValue) => this.setState({password:newValue})} placeholder="Password" />
</FormGroup>
<Button onClick={(event) => this.handleSubmit(event)}>Login</Button>
</Form>
</div>
)
}
}
The thing is, every time I clic submit, my state email/password is null, even if the fields are filled, why so?
I am still super new with JavaScript (not just react) so please explain your answer as much as you can :)
Thanks !
As you can see in the Documentation of react-bootstrap forms you'll get the newValue from your event object given to your function. So your code should look like this:
<FormControl type="username" onChange = {(event) => this.setState({email: event.target.value })} placeholder="Email" />
and do the same with your other input and everything should work fine. As far as I know, the FormControls from react-bootstrap won't give you a second parameter 'newValue'.
Use it like this
<FormControl type="username" onChange = {(event) => this.setState({email:event.target.value})} placeholder="Email" />
Now, it should work. Basically the value attached to input box is
available in event.target.value.

Resources