React - HTML form validation doesn't work - html

I work on a React project. I wrote HTML codes for create form. There is validation in HTML scripts. I wrote validations but validations doesn't work. The code is below. For example I want the relevant field to be red when the name is not entered or I want it to give a warning message when the name does not comply with the text rules. I must do it without any library. How can I fix it ?
import React, { Component } from 'react'
import EmployeeService from '../services/EmployeeService';
class CreateEmployeeComponent extends Component {
constructor(props) {
super(props)
this.state = {
id: this.props.match.params.id,
firstName: '',
lastName: '',
emailId: ''
}
}
componentDidMount(){
if(this.state.id === '_add'){
return
}else{
EmployeeService.getEmployeeById(this.state.id).then( (res) =>{
let employee = res.data;
this.setState({firstName: employee.firstName,
lastName: employee.lastName,
emailId : employee.emailId
});
});
}
}
saveOrUpdateEmployee = (e) => {
e.preventDefault();
let employee = {firstName: this.state.firstName, lastName: this.state.lastName, emailId: this.state.emailId};
console.log('employee => ' + JSON.stringify(employee));
// step 5
if(this.state.id === '_add'){
EmployeeService.createEmployee(employee).then(res =>{
this.props.history.push('/employees');
});
}else{
EmployeeService.updateEmployee(employee, this.state.id).then( res => {
this.props.history.push('/employees');
});
}
}
changeFirstNameHandler= (event) => {
this.setState({firstName: event.target.value});
}
changeLastNameHandler= (event) => {
this.setState({lastName: event.target.value});
}
changeEmailHandler= (event) => {
this.setState({emailId: event.target.value});
}
cancel(){
this.props.history.push('/employees');
}
getTitle(){
if(this.state.id === '_add'){
return <h3 className="text-center">Add Employee</h3>
}else{
return <h3 className="text-center">Update Employee</h3>
}
}
onSubmit = e => {
e.preventDefault();
}
render() {
return (
<div>
<br></br>
<div className = "container">
<div className = "row">
<div className = "card col-md-6 offset-md-3 offset-md-3">
{
this.getTitle()
}
<div className = "card-body">
<form onSubmit={this.onSubmit} noValidate>
<div className = "form-group">
<label for="validationCustom01" class="form-label">First name</label>
<input type='text' maxLength={20} pattern='[A-Za-z]' placeholder="First Name" name="firstName" className="form-control"
value={this.state.firstName} onChange={this.changeFirstNameHandler} required/>
</div>
<div className = "form-group">
<label> Last Name: </label>
<input type='text' maxLength={20} pattern='[A-Za-z]'class="form-control" placeholder="Last Name" name="lastName" className="form-control"
value={this.state.lastName} onChange={this.changeLastNameHandler} required/>
</div>
<div className = "form-group">
<label> Email Id: </label>
<input type='email' maxLength={35} pattern='[A-Za-z]' placeholder="Email Address" name="emailId" className="form-control"
value={this.state.emailId} onChange={this.changeEmailHandler} required/>
</div>
<button type="submit" className="btn btn-success" onClick={this.saveOrUpdateEmployee}>Save</button>
<button className="btn btn-danger" onClick={this.cancel.bind(this)} style={{marginLeft: "10px"}}>Cancel</button>
</form>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default CreateEmployeeComponent

Remove noValidate from your <form> element.
Additionally, I've personally found that Formik and Yup can be a helpful library.
(Sorry I missed that "no libraries" wasa constraint)
Edit:
I was a muppet and forgot to change the pattern
You can do one of 2 things:
Remove maxLength and change the pattern to pattern="[A-Za-z]{1,20}"
Where 20 will be the new max-length (so 20 or 35, depending on the field)
Only change the pattern to be pattern="[A-Za-z]+"
The + is needed to ensure 1 or more of the [A-Za-z] regex is done. https://regexr.com/
Also don't forget to remove noValidate from your <form> element.
This answer may also prove helpful in setting custom validity status messages and callbacks.

Related

How to Pass JSON data inside HTML attributes

I have created a form using HTML and trying to pass the value of a JSON object in the HTML attribute. I have used fetch to get the data from the api and used it to create options in my page that is made using vueJS. The problem is, the value that gets logged in the database is {{item}} instead of the value in the item.
How to resolve this issue?
AddLog.vue code:
<template>
<h1 style="margin-top: 107px; text-align: center;color: ;">Log the values into the tracker</h1>
<form #submit.prevent="submit" style="margin-right: 522px;margin-top: 29px; margin-left: 519px" method="POST">
<div class="form-group">
<label for="exampleInputEmail1" required style="color: ;">Note</label>
<input type="name" class="form-control" v-model="data.note" id="exampleInputEmail1" aria-describedby="emailHelp" name="Note" placeholder="Note" style="border-radius: 20px;">
</div>
<div class="form-group" v-if="this.trackertype==='Numerical'" >
<label for="exampleInputPassword1" required style="color: ;">Enter the Value</label>
<input type="value" class="form-control" v-model="data.value" id="exampleInputPassword1" name="value" placeholder="Value" style="border-radius: 20px;" required>
</div>
<div class="multiple-choice" v-else>
<label for="value" style="color: ;">Check the value</label>
<div class="form-check">
<div v-for="item,index in this.trackersettings" :key="index">
<input type="radio" name="value" v-model="data.value" value="{{item}}" required>
<label>{{item}}</label>
</div>
</div>
</div>
<button type="submit" class="btn btn-outline-dark" style="border-radius: 15px;">submit</button>
</form>
</template>
<script>
import { reactive } from 'vue';
import axios from 'axios';
export default {
Name: 'AddLog',
data(){
return{
uid : this.$route.params.uid,
tid : this.$route.params.tid,
items : [],
trackertype: '',
trackersettings: []
}
},
mounted() {
localStorage.setItem('uid',this.uid)
localStorage.setItem('tid',this.tid)
axios.get('http://localhost:5000/addLog/'+this.uid+'/'+this.tid)
.then((resp ) => {
this.items = resp.data
this.trackertype = this.items[0]['data']['trackertype']
this.trackersettings =this.items[1]['tracker_settings']
console.log(this.trackertype,this.trackersettings)
})
.catch((err) => {
console.log(err.resp)
})
},
setup() {
const data = reactive({
note: '',
value: ''
})
const submit = async () => {
await fetch("http://localhost:5000/addLog/"+localStorage['uid']+'/'+localStorage['tid'],{
method: 'POST',
headers: {'Content-Type' : 'application/json','Access-Control-Allow-Origin': '*'},
body: JSON.stringify(data)
}).then(resp => resp.json())
.then(data => {console.log(data);})
.catch(error => { console.log(error)
})
}
return {
data,
submit,
}
}
}
</script>
<style>
</style>
API code:
#app.route('/addLog/<int:uid>/<int:tid>', methods=['GET', 'POST'])
def log(uid,tid):
cell = tracker.query.filter_by(u_id=uid,tracker_id=tid).first()
l = cell.tracker_settings.split(',')
d = {
'userid' : cell.u_id,
'trackerid' : cell.tracker_id,
'trackername' : cell.tracker_name,
'trackerdesc' : cell.tracker_description,
'trackertype' : cell.tracker_type,
'tracker_settings' : cell.tracker_settings,
'datecreated' : cell.date_created
}
if request.method=='POST':
data = request.json
val = data['value']
note = data['note']
cell = logtable(user_id=uid,t_id=tid,Note=note,value=val)
db.session.add(cell)
db.session.commit()
return jsonify({'message':'success'})
else:
return jsonify({'data':d},{'tracker_settings' : l })
I want the values in the options to be logged in the db.
Instead of the "{{item}}" in the value , I need the string "Gloomy". Can Anybody help me on doing this?
Here is the correct way to assign the value :
Try :value="item" instead of value="{{item}}"
Demo :
var app = new Vue({
el: '#app',
data: {
selected: '',
item1: 'Male',
item2: 'Female'
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Binding Radio</h2>
<input type="radio" id="one" :value="item1" v-model="selected">
<label for="one">Male</label>
<br>
<input type="radio" id="two" :value="item2" v-model="selected">
<label for="two">Female</label>
<br>
<span>Picked: {{ selected }}</span>
</div>

Why is my axios get request is not working (login)

I´m currently working on a login-page for a school-prohect. I´m using vue.js and tried to use axios to run my get-request. My problem is, that I don´t even get into .then() --> alert(TEST1) is the last thing showed.
I don´t get any error
Does anyone know why I have this problem and how to solve it?
Thanks!
CODE:
<template>
....
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6" id="formsCSS">
<form id="login" method="get">
<div class="form-group">
<input type="text" name="username" id="username" class="form-control" placeholder="Username" required maxlength="50">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" id="password" placeholder="Password" required>
</div>
<button #click="login" type="submit" name="login_button" class="block">Login</button>
</form>
....
</div>
</template>
<script>
//import axios from './node_modules/axios/index.js';
import axios from 'axios';
export default {
methods: {
login() {
var usrn = document.getElementById("username").value;
var passwd = document.getElementById("password").value;
var usesGranted = 50;
alert("TEST0");
this.doGetRequest(usrn, passwd, usesGranted, false);
},
doGetRequest(passwd, usrn, usesGranted, logedIn) {
alert("TEST1");
axios.get('https://moray.xyz/trawaapi/token/obtainToken.php', {
data: {
auth: {
username: usrn,
password: passwd
},
uses: usesGranted
}
})
.then((response) => {
//Informationen die für Requests benötigt werden in der sessionStorage abspeichern
alert("TEST2");
console.log(response);
sessionStorage.setItem("token", response);
sessionStorage.setItem("password", passwd);
sessionStorage.setItem("username", usrn);
sessionStorage.setItem("uses", usesGranted)
})
.catch((error) => {
//Neuen Token anfordern
if (error == 401) {
if (logedIn == true)
alert("....");
}
console.error(error);
});
}
}
};
</script>
You have to prevent form from being sent. Change remove onclick from button and add another event to the form tag:
<form #submit.prevent="yourFunction" id="login">
As we prevent Email sending and just running yourFunction - we do not need to use method attribute.

show login page for a second when routering other pages reactJS

I use this video https://www.youtube.com/watch?v=r4EsP6rovwk&t=1s to create an Auth for my website,
i basically copied his code the only change is that I route after successful login to different page.
the problem is that after login my home page is shown, but when I'm pressing buttons to route for other pages, before the other page is shown I see for a second the login page.
this is the code of the auth - I believe it connect to the problem (before this my website has worked well).
Edit:
i try to figure out what's the problem and I've noticed that when i'm using link everything's fine, but when using href there's a problem.
(And that's what I did in my website).
So... does anyone know why href makes this issue?
app.js
import React, { Component } from 'react';
import fire from './Fire';
import SearchAppBar from '../components/appBar';
import Login from './login';
class App extends Component {
constructor() {
super();
this.state = ({
user: null,
});
this.authListener = this.authListener.bind(this);
}
componentDidMount() {
this.authListener();
}
authListener() {
fire.auth().onAuthStateChanged((user) => {
if (user) {
this.setState({ user });
} else {
this.setState({ user: null });
}
});
}
render() {
return (
<div>{this.state.user ? ( <SearchAppBar/>) : (<Login />)}</div>)
}
}
export default App;
login.js:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import fire from './Fire';
class Login extends Component {
constructor(props) {
super(props);
this.login = this.login.bind(this);
this.handleChange = this.handleChange.bind(this);
this.signup = this.signup.bind(this);
this.state = {
email: '',
password: ''
};
}
handleChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
login(e) {
e.preventDefault();
fire.auth().signInWithEmailAndPassword(this.state.email, this.state.password).then((u)=>{
}).catch((error) => {
console.log(error);
});
}
signup(e){
e.preventDefault();
fire.auth().createUserWithEmailAndPassword(this.state.email, this.state.password).then((u)=>{
}).then((u)=>{console.log(u)})
.catch((error) => {
console.log(error);
})
}
render() {
return (
<div className="col-md-6">
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input value={this.state.email} onChange={this.handleChange} type="email" name="email"
class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter
email" />
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.
</small>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input value={this.state.password} onChange={this.handleChange} type="password" name="password"
class="form-control" id="exampleInputPassword1" placeholder="Password" />
</div>
<button type="submit" onClick={this.login} className="btn btn-primary">Login</button>
<button onClick={this.signup} style={{marginLeft: '25px'}} className="btn btn-
success">Signup</button>
</form>
</div>
);
}
}
export default Login;
Thank you all guys!!

How to correctly update form, react state with axios post request?

I'm currently making a post request using axis but the data I pass into my form isn't being updated.
I keep receiving a 404 error.I think it might be the form info isn't being passed to the post request.
I do think my logic is correct, the only issue I can think go is how I'm accessing the address object in my state maybe or how the keys in address is accessed in the input tags.
This is how the JSON POST body should be:
{
"first_name": "Craig",
"last_name": "Williams",
"address": {
"line_1": "123 Mark Lane",
"line_2": "3B",
"city": "Brooklyn",
"region": "NY",
"postal": "41211"
}
}
Current after the form is filled out I console log the state in onSubmit nd this is what is logged. It's incorrect, it should be more like the JSON body.
{first_name: "Craig",
last_name: "Williams",
address: "123 Mark Lane",
line_2: "41211"}
Currently my code looks like this:
import React from 'react';
import axios from 'axios';
class App extends React.Component{
state = {
first_name : '',
last_name : '',
address : {
line_1: '',
line_2: '',
city: '',
state: '',
zipcode: ''
}
}
onChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
}
onSubmit = (e) => {
e.preventDefault();
const {first_name,last_name,address} = this.state;
console.log(address)
axios.post(`website to hit`,{first_name,last_name,address})
.then((result) => {
this.setState({ result.data });
}) .catch((error)=> {
console.log(error);
});
}
render() {
const { first_name, last_name, address } = this.state;
return (
<div className="App">
<div className="left">
<h1>Rocket Insurance</h1>
<h1 className='p-left'>As interplanetary travel becomes mainstream </h1>
</div>
<div className="right">
<h2>Recieve a free qoute today</h2>
<div className="form">
<form onSubmit={this.onSubmit}>
<input
type="text"
name="first_name"
placeholder='First Name'
value={first_name}
onChange={this.onChange}
/>
<input
type="text"
name="last_name"
placeholder='Last Name'
value={last_name}
onChange={this.onChange}
/>
<input
type="text"
name="address"
placeholder='Street'
value={address['line_1']}
onChange={this.onChange}
/>
<input
type="text"
name="line_2"
placeholder='Apt number'
value={address['line_2']}
onChange={this.onChange}
/>
<input
type="text"
name="line_2"
placeholder='City'
value={address['city']}
onChange={this.onChange}
/>
<input
type="text"
name="line_2"
placeholder='State'
value={address['region']}
onChange={this.onChange}
/>
<input
type="text"
name="line_2"
placeholder='zipcode'
value={address['region']}
onChange={this.onChange}
/>
<button className='button-sign-in'>Log in</button>
</form>
</div>
</div>
</div>
);
}
}
export default App;
In should resolve your issue. Your input names were not matching the state values you were trying to change. Your handleChange handler was not designed to handle nested objects however, so i rather flattened your state and on submit, i structure the state to resemble the required object shape for post
class Form extends React.Component {
state = {
first_name: "",
last_name: "",
line_1: "",
line_2: "",
city: "",
state: "",
zipcode: ""
};
onChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
onSubmit = e => {
e.preventDefault();
const { first_name, last_name, ...address } = this.state;
console.log({ first_name, last_name, address: { ...address } });
// axios.post(`https://fed-challenge-api.sure.now.sh/api/v1/quotes`,{ first_name, last_name, address: { ...address } })
// .then((result) => {
// console.log("QUOTE:",result)
// this.setState({ result.data });
// }) .catch((error)=> {
// console.log(error);
// });
};
render() {
const {
first_name,
last_name,
zipcode,
line_1,
line_2,
city,
state
} = this.state;
return (
<div className="App">
<div className="left">
<h1>Rocket Insurance</h1>
<h1 className="p-left">
As interplanetary travel becomes mainstream, we're excited to offer
rocket owners comprehensive coverage options to let them fly through
space worry-free{" "}
</h1>
</div>
<div className="right">
<h2>Recieve a free qoute today</h2>
<div className="form">
<form onSubmit={this.onSubmit}>
<input
type="text"
name="first_name"
placeholder="First Name"
value={first_name}
onChange={this.onChange}
/>
<input
type="text"
name="last_name"
placeholder="Last Name"
value={last_name}
onChange={this.onChange}
/>
<input
type="text"
name="line_1"
placeholder="Street"
value={line_1}
onChange={this.onChange}
/>
<input
type="text"
name="line_2"
placeholder="Apt number"
value={line_2}
onChange={this.onChange}
/>
<input
type="text"
name="city"
placeholder="City"
value={city}
onChange={this.onChange}
/>
<input
type="text"
name="state"
placeholder="State"
value={state}
onChange={this.onChange}
/>
<input
type="text"
name="zipcode"
placeholder="zipcode"
value={zipcode}
onChange={this.onChange}
/>
<button className="button-sign-in">Log in</button>
</form>
</div>
</div>
</div>
);
}
}
export default Form;

Convert HTML form with action to React form submit with logic

Folks, I think I'm either missing something here or I don't know what I don't know.
What I have is:
<form action="/orders/populate" method="post">
<input type="hidden" name="name" id="name"/>
<input type="hidden" name="rating" id="rating"/>
<input type="submit" name="commit" value="Rate Now" />
</form>
What I want to do is:
Class myComponent extends React.PureComponent {
handleSubmit(e) {
e.preventDefault(); // don't know if this is necessary
sendAnalytics();
// then form submit
}
render () {
return (
<form action="/orders/populate" method="post" onSubmit={this.handleSubmit.bind(this)}>
<input type="hidden" name="name" id="name"/>
<input type="hidden" name="rating" id="rating"/>
<input type="submit" name="commit" value="Rate Now" />
</form>
);
}
}
Don't know what has to be done here. Can someone point out an example similar to this? Or perhaps give me a sample code below?
All help appreciated.
Class myComponent extends React.PureComponent {
this.state = {
name: '' // initial value for name
rating: '' // initial value for rating
}
handleInput = e => {
this.setState({[e.target.name]: e.target.value})
}
handleSubmit = e => {
const { name, rating } = this.state;
e.preventDefault(); // yes, this is necessary otherwise it's refresh your page.
sendAnalytics(name, rating); // api call to store in DB. to call API use axios npm package
}
render () {
const { name, rating } = this.state;
return (
<form onSubmit={this.handleSubmit}>
<input type="text" name="name" value={name} id="name" onChange={(e) => this.handleSubmit(e)}/>
<input type="text" name="rating" value={rating} id="rating" onChange={(e) => this.handleSubmit(e)}/>
<input type="submit" name="commit" value="Rate Now" />
</form>
);
}
}
Have you looked at the docs for handling forms in React? This will give you insights in how to use forms with react, since it handles a bit different than regular html forms
This is a common problem I've faced in React. You have one of three ways:
1) Use a third party React-Form library to do the job. There are several.
2) Use React-hooks (a very recent addition to React).
3) Create a generic Form class to handle this state management for you...like so:
export default class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
values: {}
};
}
#boundMethod
handleSubmit(event) {
event.preventDefault();
this.props.submit(this.state.values);
}
#boundMethod
handleChange(event) {
const { name, value } = event.target;
const newValues = Object.assign(
{ ...this.state.values },
{ [name]: value }
);
this.setState({
values: newValues
});
}
public render() {
const { values } = this.state;
return (
<form onSubmit={this.handleSubmit} noValidate={true}>
<div>
{React.Children.map(
this.props.children,
child => (
{React.cloneElement(child, {
value: values[child.props.name],
onChange: this.handleChange
})}
)
)}
<div>
<button type="submit">
Submit
</button>
</div>
</div>
</form>
);
}
}
Then you will be able to use this Form class like so:
<Form
submit={values => {
/* work with values */
}}
>
<input type="hidden" name="name" />
<input type="hidden" name="rating" />
</Form>;
PS:
Keep in mind boundMethod Decorator is something that is not natively available but a module called 'autobind-decorator' I tend to use a lot to deal with this not being bound.