Form validation with NuxtJS - javascript

I'm new to NuxtJS, I was trying to do a simple form to try things out.
The idea is that I have a component that contains the full form
<template>
<div>
<h1>
{{ title }}
</h1>
<form #submit.prevent="handleSubmit">
<input type="email" v-model="email" />
<input type="password" v-model="password" />
<button type="submit">Sign in</button>
</form>
</div>
</template>
<script>
export default {
data: function() {
return {
title: 'Sign in',
email: null,
password: null
}
},
methods: {
handleSubmit: function() {
console.log('Hello')
}
}
}
</script>
It's nothing crazy, and then I'm just calling this component in my page
<template>
<LoginForm />
</template>
<script>
export default {
}
</script>
But when I submit my form I can't see my message in the console, I'm wondering what I did wrong or did I miss something ?
Also it is a good practice to make a component like this or should I divide more my component into small one's ?

Related

Render components based on state

I am working on a user registration/ log in page. I have two forms, a signUp form and a logIn form, and some state called signInState that determines which user form to display. I have two buttons that toggle the signInState, and if the signInState is true, I want it to display the log in form, if its false, I want to display the sign up form. The state is changing, but for some reason the conditional rendering is not working. Can someone help me figure out why my toggleSignInState doesn't change what's being rendered on the page? Thanks
Here is my react code for the signInPage itself
import React from 'react'
import SignUp from './SignUp'
import LogIn from './LogIn'
export default function SignInPage() {
const [signInState, setSignInState] = React.useState(true);
function toggleSignIn(event) {
console.log(event.target.id)
setSignInState(event.target.id);
/*setSignInState(event.target.value);*/
}
return (
<div className="signInPage">
<div className="signInPageFormContainer">
<p>{signInState}</p>
{!signInState && <SignUp /> }
{signInState && <LogIn /> }
<div className="signUpPageToggleContainer">
<button onClick={toggleSignIn} id='true'>Log In</button>
<button onClick={toggleSignIn} id='false'>Sign Up</button>
</div>
</div>
</div>
)
}
here is the code for the signUp form
import React from 'react'
export default function SignUp() {
return(
<form className="signUpForm">
<input
name="username"
type="text"
placeholder="Username"
className="signUpInput"
/>
<input
name="email"
type="text"
placeholder="Email"
className="signUpInput"
/>
<input
name="password"
type="text"
placeholder="Password"
className="signUpInput"
/>
<input
name="confirmPassword"
type="text"
placeholder="Confirm password"
className="signUpInput"
/>
<div>
<button>Sign Up</button>
<button>Cancel</button>
</div>
</form>
)
}
and here is the code for the log in form
import React from "react";
export default function LogIn() {
/*functions for log in procedure*/
return (
<form className="logInForm">
<input
placeholder="Username"
name="username"
type="text"
id="username"
className="logInFormInput"
/>
<input
placeholder="Password"
name="password"
type="text"
id="password"
className="logInFormInput"
/>
<div className="logInFormButtonContainer">
<button className="logInFormButton">Log In</button>
<button className="logInFormButton">Cancel</button>
</div>
</form>
)
}
Element attributes are strings. The string 'true' is not the same as the boolean true, and the string 'false' is not the same as the boolean false. Both 'true' and 'false' are truthy, so signInState is always truthy.
While you could perform string comparisons inside toggleSignIn to determine what to pass to the state setter, calling the state setter inline in the buttons would be easier.
<button onClick={() => { setSignInState(true); }}>Log In</button>
<button onClick={() => { setSignInState(false); }}>Sign Up</button>
Here the id from event object will always be Boolean true as they are not booleans they are strings, i.e., whatever you keep as value in a DOM attribute it would be a string in most of the cases and any string except empty string "" is true ...
The answer from CertainPerformance is better and easy to understand
In case you want to keep your code same and changing a little as below should work
function toggleSignIn(event) {
setSignInState(event.target.id === "true" ? true : false);
}

How to 'useState' correctly in Formik 'onSubmit' function?

I'm using Formik in my Next.js app, and i ran into a problem that I'm not sure how to fix. My submit Button is a component that accepts a showSpinner prop. If it is true -> button is disabled and a loading spinner in a button is displayed. showSpinner value depends on loading that is coming from useState hook. Here is a relevant code:
export default function register() {
const [loading, setLoading] = useState(false)
return (
<>
<Layout>
<div className={styles.registerContainer}>
<div className={styles.registerFormContainer}>
<h1 className={styles.registerHeader}>Sign Up</h1>
<Formik
initialValues={{
email: '',
password: '',
passwordConfirm: '',
acceptedTerms: false
}}
onSubmit={
(values, { setSubmitting }) => {
console.log(loading)
// here loading == false as expected
setLoading(true)
console.log(loading)
// here loading == false even though i set it to true
initFirebase()
firebase.auth().createUserWithEmailAndPassword(values.email, values.password)
.then((res) => {
console.log('done!')
})
.catch(function (error) {
// Handle Errors here.
console.log(error)
})
.finally(() => {
console.log(loading)
//here loading == false too, even though I expected it to be true
setSubmitting(false)
setLoading(false)
})
}
}
>
<Form>
<FormikText label="Email:"
name="email"
type="email"
id="email" />
<FormikPassword label="Password:"
name="password"
id="password"
/>
<FormikPassword label="Confirm Password:"
name="passwordConfirm"
id="passwordCOnfirm"
/>
<FormikCheckbox
name="acceptedTerms"
id="acceptedTerms"
>
<span className={styles.checkboxLabel}>
I agree to the <Link href="/terms" ><a className={styles.registerLink}>Terms of Service</a></Link> and <Link href="/privacy"><a className={styles.registerLink}>Privacy/Cookie Policy</a></Link>
</span>
</FormikCheckbox>
<div className={styles.buttonContainer}>
<Button type="submit" color="blue" showSpinner={loading}>Sign Up</Button>
</div>
</Form>
</Formik>
</div>
</div>
</Layout>
</>
)
}
Even though my Button is somehow working as expected (spinner is displayed as intended), after console.loging value of loading through onSubmit function call I noticed that it is false were I expected it to be true. Is it due to the way React batches useState calls?
My questions are:
How to handle this scenario in a right way?
If loading == false in those console.logs, why is my Button working as intended ?
is it due to the way React batches useState calls?
I think so, that's precisely why Formik provides a isSubmitting flag, try using it instead of tracking your own loading state, I know it's working for your current specs but you could have some issues when this component gets more complex
Your code would look like this
export default function register() {
return (
<>
<Layout>
<div className={styles.registerContainer}>
<div className={styles.registerFormContainer}>
<h1 className={styles.registerHeader}>Sign Up</h1>
<Formik
initialValues={{
email: "",
password: "",
passwordConfirm: "",
acceptedTerms: false,
}}
onSubmit={async (values) => {
try {
initFirebase();
await firebase
.auth()
.createUserWithEmailAndPassword(
values.email,
values.password
);
} catch (e) {
// Handle Errors here.
console.log(error);
}
}}
>
{({ isSubmitting }) => (
<Form>
<FormikText
label="Email:"
name="email"
type="email"
id="email"
/>
<FormikPassword
label="Password:"
name="password"
id="password"
/>
<FormikPassword
label="Confirm Password:"
name="passwordConfirm"
id="passwordCOnfirm"
/>
<FormikCheckbox name="acceptedTerms" id="acceptedTerms">
<span className={styles.checkboxLabel}>
I agree to the{" "}
<Link href="/terms">
<a className={styles.registerLink}>Terms of Service</a>
</Link>{" "}
and{" "}
<Link href="/privacy">
<a className={styles.registerLink}>
Privacy/Cookie Policy
</a>
</Link>
</span>
</FormikCheckbox>
<div className={styles.buttonContainer}>
<Button
type="submit"
color="blue"
showSpinner={isSubmitting}
>
Sign Up
</Button>
</div>
</Form>
)}
</Formik>
</div>
</div>
</Layout>
</>
);
}
taken from here https://formik.org/docs/examples/async-submission

How to keep semantic-ui modal from closing when displaying different components?

I am trying to use a modal for authentication (login and register). So far I have been able to get it to display correctly and can switch from login to register component, but for some reason the modal will close after trying to switch back from register to login. I have a header that contains the trigger for the modal. Here is my code so far:
Header.js
import React, { Component } from "react";
import Login from "./Login";
import Register from "./Register";
import logo from "../assets/logo.png"
import { Modal } from "semantic-ui-react";
class Header extends Component {
constructor(props){
super(props);
this.state = { login: true, header: "Login"}
this.handleRegister = this.handleRegister.bind(this);
this.handleLogin = this.handleLogin.bind(this);
}
handleRegister = () => {
this.setState({ login: false,
header: "Register"});
}
handleLogin = () => {
this.setState({ login: true,
header: "Login"});
}
renderModal () {
const showLogin = this.state.login ? (<Login handleRegister={this.handleRegister} />) : (<Register handleLogin={this.handleLogin} />);
return (
<Modal closeIcon onClose={this.handleLogin} size="tiny" trigger={<a className="item">Login</a>}>
<Modal.Header style={{backgroundColor: "#005ce6", color:"white"}}>{this.state.header}</Modal.Header>
<Modal.Content>
{showLogin}
</Modal.Content>
</Modal>
)
}
render() {
return (
<div>
<div className="ui menu hover" style={{ padding: 0}}>
<div className="right menu">
{this.renderModal()}
</div>
</div>
</div>
)
}
}
export default Header;
Register.js
import React, { Component } from 'react';
class Register extends Component {
constructor(props){
super(props)
this.handleLogin = this.props.handleLogin.bind(this);
}
render() {
return (
<div>
<div>
<form action="/auth/register" method="post" className="ui form">
<div className="field">
<label>First Name</label>
<input type="text" placeholder="First Name" name="firstName"/>
</div>
<div className="field">
<label>Last Name</label>
<input type="text" placeholder="Last Name" name="lastName"/>
</div>
<div className="field">
<label>Email</label>
<input type="text" placeholder="Email" name="email"/>
</div>
<div className="field">
<label>Password</label>
<input type="password" placeholder="Password" name="password"/>
</div>
<button type="submit" className="ui button">Submit</button>
</form>
<div style={{paddingTop:20}}>
<div>Already have account? Please <a onClick={this.handleLogin}>Login</a></div>
</div>
</div>
</div>
)
}
}
export default Register;
Login.js
import React, { Component } from 'react'
class Login extends Component {
constructor(props){
super(props)
this.handleRegister = this.props.handleRegister.bind(this);
}
render(){
return (
<div>
<form action="/auth/login" method="post" className="ui form">
<div className="field">
<label>Email</label>
<input type="text" placeholder="Email" name="email"/>
</div>
<div className="field">
<label>Password</label>
<input type="password" placeholder="Password" name="password"/>
</div>
<button type="submit" className="ui button">Submit</button>
</form>
<div style={{paddingTop:20}}>
<div>Don't have an account? Please <a onClick={this.handleRegister}>Register</a></div>
</div>
</div>
)
}
}
export default Login;
I have tried using the open field for the modal and setting a "show" state depending if the trigger is set off, but it ends up never closing. It seems that when I go from register to login components via the "Login" click it will set off a close event and I can not figure out why.
Workaround: add closeOnDimmerClick={false} as Modal prop.
Source: https://github.com/Semantic-Org/Semantic-UI-React/issues/2493#issuecomment-362972834
There are some issues with Modal component of Semantic UI React. Definitely.
Repro steps:
https://codesandbox.io/s/30n2v379r1
open modal by clicking Login (top left corner, also zoom out to see the links of modal)
click Register link of the modal
click Login link of the modal
Actual: modal is closed
Expected: modal is open and Register form is displayed
IMO, after changing the markup (Register form has more inputs) navigation link has new coordinates which is out of initial coords range of the modal. Therefore, clicking on this link now is treated like a clicking somewhere outside of the modal.
PS: yet another way to escape this auto-closing behavior is to make both forms markup more or less similar: for example, remove first two inputs from Register form so it looks exactly like Login form (of course, it's not the solution for topic-starter, just FYI), there are some comments in Register component on https://codesandbox.io/s/30n2v379r1
upd: issue on SUIR repo https://github.com/Semantic-Org/Semantic-UI-React/issues/2888
Use open property, it's boolean if true will keep your modal open.
demo link to keep modal open
<Modal
trigger={<Button onClick={this.handleOpen}>Show Modal</Button>}
open={this.state.modalOpen}
onClose={this.handleClose}
basic
size='small'
>

Form Submit using reactjs

I am new in reactjs. I am creating a sample project using reactjs. First I am getting error like state is null. After setting intial state i am getting error
I got Warning: valueLink prop on input is deprecated; set value and onChange instead
I know there are many question related to this but my problem is not solved please help.
Here is code:
import React, {Component} from 'react';
import {Link} from 'react-router'
import validator from 'validator';
import LinkedStateMixin from 'react-addons-linked-state-mixin';
module.exports = React.createClass({
mixins: [LinkedStateMixin],
getInitialState() {
return {};
},
saveData: function(){
//console.log(this.state)
},
render () {
return (
<form>
<div className="page-content container">
<div className="row">
<div className="col-md-4 col-md-offset-4">
<div className="login-wrapper">
<div className="box">
<div className="content-wrap">
<h6>Sign Up</h6>
<input className="form-control" name ="email" placeholder="E-mail address" type="text" valueLink={this.linkState('email')}/>
<input className="form-control" name="password" placeholder="Password" type="password"/>
<input className="form-control" placeholder="Confirm Password" type="password" />
<div className="action">
<button type="button" className ="btn btn-primary signup" onClick={this.saveData}>Sign Up</button>
</div>
</div>
</div>
<div className="already">
<p>Have an account already?</p>
<Link to ="/reactApp/">Login</Link>
</div>
</div>
</div>
</div>
</div>
</form>
)
}
});
Please read more about the fundamentals of React and handling state in forms in the React documentation. No mixins or anything complicated required. Also as stated above "ReactLink is deprecated as of React v15. The recommendation is to explicitly set the value and change handler, instead of using ReactLink."
Each of your text inputs should have a change handler just like the error message says... There are many ways you could accomplish this but below is a basic example. Check out the snippet below in a fiddle here https://jsfiddle.net/09623oae/
React.createClass({
getInitialState: function() {
return({
email: "",
password: "",
passwordConfirmation: ""
})
},
submitForm: function(e) {
e.preventDefault()
console.log(this.state)
},
validateEmail: function(e) {
this.setState({email: e.target.value})
},
validatePassword: function(e) {
this.setState({password: e.target.value})
},
confirmPassword: function(e) {
this.setState({passwordConfirmation: e.target.value})
},
render: function() {
return (
<form onSubmit={this.submitForm}>
<input
type="text"
value={this.state.email}
onChange={this.validateEmail}
placeholder="email"
/>
<input
type="password"
value={this.state.password}
onChange={this.validatePassword}
placeholder="password"
/>
<input
type="password"
value={this.state.passwordConfirmation}
onChange={this.confirmPassword}
placeholder="confirm"
/>
</form>
)
}
});
Solution
You cannot use valueLink anymore, instead use onChange react event to listen for input change, and value to set the changed value.
class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'Hello!'};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
render() {
return (
<input
type="text"
value={this.state.value}
onChange={this.handleChange}
/>
);
}
Clarification
Notice that since the value is set from a state, it will only get updated from changing the attached state, writing in the input does nothing, unless you listen for the input changed (via onChange event) and update the state accordingly.
source: from React documentation
You should set your state to atleast empty initially, if you want to access it at a later point of time. Something similar to below will do
getInitialState() {
return {};
},
ReactLink Without valueLink
You can change with
<input type="text" value={valueLink.value} onChange={handleChange} />
Reference:
https://facebook.github.io/react/docs/two-way-binding-helpers.html
This warning happens because the React Link was deprecated in React 0.15:
ReactLink is deprecated as of React v15. The recommendation is to
explicitly set the value and change handler, instead of using
ReactLink.
So, instead of use this.linkState('email') and valueLink:
<input className="form-control"
name ="email"
placeholder="E-mail address"
type="text"
valueLink={this.linkState('email')}/>
Use this.state.email and an onChange function:
callThisWhenChangeEmail: function(emailFromInput) {
this.setState({
email: emailFromInput
});
},
render () {
/* the existent code above */
<input className="form-control"
name ="email"
placeholder="E-mail address"
type="text"
value={this.state.email}
onChange={this.callThisWhenChangeEmail}/>
/* the existent code below */
}
When the user type some e-mail in the input, the function callThisWhenChangeEmail is called, receiving the e-mail as parameter (emailFromInput). So, you only need to set this e-mail in the state.

ReactJs submitting form data to the screen

I want a way to submit a form in ReactJs to the browser.
var ToDoForm = React.createClass({
getInitialState: function() {
return {text: ''};
},
handleChange: function(event) {
this.setState({text: event.target.value});
},
handleSubmit: function(e) {
e.preventDefault();
return (
<h2> hey </h2>
)
},
render: function() {
return (
<div>
<h1> todos </h1>
<form className="todoForm" onSubmit={this.handleSubmit}>
<input
type="text"
placeholder="Type out a task"
value={this.state.text}
onChange={this.handleChange}
/>
<input
type="submit"
value="Submit todo"
/>
</form>
</div>
);
}
});
I have a function handleSubmit that I want when the form is submitted to just print the word hey in the browser as a heading2. I know this is not very wise or makes any sense but I just want to see it working and then I'll it to return something that makes more sense. So far when I click on the submit button, nothing happens. any solutions?
also worth adding, this question (Get form data in Reactjs). I want what this guy is basically doing but instead of console.logs an actual print to screen, just to clarify if I have been unclear
Use a state to handle it ? Something like
getInitialState: function(){
return{
submitted: false
},
handleSubmit: function(e){
e.preventDefault();
this.setState({ subbmitted: true});
},
render: function(){
return (
<div>
<h1> todos </h1>
{!!this.state.submitted ?
<div>
<h2> {'Hey'} </h2>
</div>
:
<form className="todoForm" onSubmit={this.handleSubmit}>
<input
type="text"
placeholder="Type out a task"
value={this.state.text}
onChange={this.handleChange}
/>
<input
type="submit"
value="Submit todo"
/>
</form>
</div>
)

Categories

Resources