I'm using React with express to render the views of my project server-side but I came across a problem.
I have a component where the users go after loging in for the first time. There are two inputs to write the user's new password and to confirm it. I'm trying to validate that the password entered is 8 characters long at least and that the value of both inputs is the same.
React doesn't seems to update the component state and thus, my verification process doesn't work. Am I doing something wrong? Here's the code:
set-password.jsx
module.exports = React.createClass({
getInitialState: function() {
return {
sPassword: '',
validLength: false,
validPassword: false
}
},
checkLength: function(event) {
var pLength = event.target.value;
pLength.length >= 8 ?
this.setState({ validLength: true }) :
this.setState({ validLength: false });
},
checkPassword: function(event) {
event.target.value === this.state.sPassword ?
this.setState({ validPassword: true, sPassword: event.target.value}) :
this.setState({ validPassword: false });
},
render: function() {
return (
<Layout>
<Form action='/auth/setpassword' method='POST' name='setPassword'>
<h1>Welcome</h1>
<p>...</p>
<div className='row'>
<div className='col-sm-6'>
<Input
type='password'
label='Introduzca su nueva contraseña'
name='password'
onChange={this.checkLength}
value={this.state.sPassword}
/>
</div>
<div className='col-sm-6'>
<Input
type='password'
label='Escriba de nuevo su contraseña'
name='confirm_password'
onChange={this.checkPassword}
/>
</div>
</div>
<SubmitButton value='Guardar nueva contraseña' />
<div>
<p>Contraseña verificada: <span>{this.state.sPassword}</span></p>
</div>
</Form>
</Layout>
)
}
});
I'm using checkLength() on the first input to verify the password length. Then checkPassword() verifies that both inputs have the same code and then update this.state.sPassword to be the first input value, which will be sent to the system endpoint.
After the SubmitButton component I'm printing the value of this.state.sPassword to see if the state is changing, but it does not. Can you help me? Thanks.
Your issue is that you are not setting the value of sPassword properly from its own input, the only thing you are doing is setting it when the other input changes. Additionally, that code:
checkPassword: function(event) {
event.target.value === this.state.sPassword ?
this.setState({ validPassword: true, sPassword: event.target.value}) :
this.setState({ validPassword: false });
},
is redundant because you are setting sPassword to the same value it already has, assuming the true case passes. Basically you are saying if '123' == password then set password to '123'. Furthermore, that case will never happen because sPassword never gets updated from its own input and thus is always an empty string.
What you need to do is, instead of calling checkLength() in first inputs onChange, you call something like updateSPassword() to properly set the password. Further more you can do the same for the second input. Finally you can add a validate method that is called when either of the passwords change and that performs your validation:
module.exports = React.createClass({
getInitialState: function() {
return {
sPassword: '',
cPassword: '',
validLength: false,
validPassword: false
}
},
setSPasswordAndValidate: function(e) {
this.setState({
sPassword: e.target.value
});
this.validate();
},
setCPasswordAndValidate: function(e) {
this.setState({
cPassword: e.target.value
});
this.validate();
},
validate: function() {
var pw1 = this.state.sPassword;
var pw2 = this.state.cPassword;
var validPassword = pw1 === pw2;
var validLength = validPassword && pw1.length >= 8;
this.setState({
validPassword: validPassword,
validLength: validLength
});
}
render: function() {
// ...
<Input
type='password'
label='Introduzca su nueva contraseña'
name='password'
onChange={this.setSPasswordAndValidate}
value={this.state.sPassword}
/>
// ...
<Input
type='password'
label='Escriba de nuevo su contraseña'
name='confirm_password'
onChange={this.setCPasswordAndValidate}
value={this.state.cPassword}
/>
}
});
Or you can even combine the setting of passwords and validation into a single method:
setSPasswordAndValidate: function(e) {
this.validate(e.target.value, this.state.cPassword);
},
setCPasswordAndValidate: function(e) {
this.validate(this.state.sPassword, e.target.value);
},
validate: function(sPassword, cPassword) {
var validPassword = sPassword === cPassword;
var validLength = validPassword && sPassword.length >= 8;
this.setState({
sPassword: sPassword,
cPassword: cPassword,
validPassword: validPassword,
validLength: validLength
});
}
Related
I have a problem with reseting fields of my form.
I have a form. The user can adding another forms and another ...
If everything is OK, I would like to recording data in my DB and in my store AND reset all of inputs of my form. This is this last point I cannot do.
I have tried different solutions but It does not work.
This is my code :
<div v-for="(question, index) in questionsSignaletiques" :key="index" class="blockQuestion" >
<!--form to add questions : one form per question, each form have a different name in the ref -->
<a-form-model
layout="inline"
:ref="'p' + index"
>
<p>New question</p>
<a-alert v-if="question.error.here" type="error" :message="question.error.message" show-icon />
<a-form-model-item>
<a-input v-model="question.question.type" placeholder="Title">
</a-input>
</a-form-model-item>
<a-form-model-item>
<a-input v-model="question.question.item" placeholder="Item">
</a-input>
</a-form-model-item>
<br><br>
<a-form-model-item label="Question multiple" prop="delivery">
<a-switch v-model="question.question.multiple" />
</a-form-model-item>
<a-form-model-item label="Obligatoire" prop="delivery">
<a-switch v-model="question.question.obligatoire" />
</a-form-model-item>
<br><br>
<div class="blockChoices">
<div v-for="subrow in question.question.choices">
<a-form-model-item>
<a-input v-model="subrow.name" placeholder="Choix">
</a-input>
</a-form-model-item>
</div>
</div>
<a-button #click="addChoice(question)" type="secondary">Add a choice</a-button>
</a-form-model>
</div>
<div>
<a-button #click="addItem" type="secondary">Add a question</a-button>
</div>
<br>
<div>
<a-button #click="submit" type="primary">Send</a-button>
</div>
Javascript code :
data() {
return {
idStudy: this.$route.params.id,
aucuneQuestion:false,
questionsSignaletiques: [
{
"study":"/api/studies/" + this.$route.params.id,
"question":
{
type: "",
item: "",
multiple: false,
obligatoire: false,
inverse: false,
barometre: false,
originale: false,
signaletik: true,
choices: [{name:''}]
},
"error": {
message:"",
here:false
}
}
],
}
},
mounted() {
//retreive all the questions still recorded
axios
.get('http://127.0.0.1:8000/api/studies/' + this.idStudy + '/question_studies?question.signaletik=true')
.then((result)=>{
console.log(result.data["hydra:member"])
this.aucuneQuestion = result.data["hydra:member"].length === 0;
//on met les données dans le store
this.$store.commit("setListeQuestionsSignaletiques", result.data["hydra:member"])
})
.catch(err=>console.log(err))
},
methods: {
//Adding a question
addItem () {
this.questionsSignaletiques.push(
{
"study":"/api/studies/" + this.idStudy,
"question":
{
type: "",
item: "",
multiple: false,
obligatoire: false,
inverse: false,
barometre: false,
originale: false,
signaletik: true,
choices: [{name:''}]
},
"error": {
message:"",
here:false
}
}
)
},
//adding a choice
addChoice: function(choice) {
choice.question.choices.push({
name: ''
})
},
// Sending the forms
submit () {
//loop table to retrieve all questions and indexes if the user adding several questions
this.questionsSignaletiques.forEach((element,index) =>
{
const inputType = element.question.type
const inputItem = element.question.item
const inputChoice = element.question.choices
//loop on choices to see if empty one or not
for (const oneChoice of inputChoice)
{
if ((inputChoice.length == 1) ||(inputChoice.length == 2 && oneChoice.name == ""))
{
element.error.here=true
element.error.message = "You must have two choices at least"
return false; // stop here if error
}
else
{}
}// end loop of choices
// verify other fields
if (inputType == "" || inputItem =="")
{
element.error.here=true
element.error.message = "Title and item must not be empty"
}
else
{
// everything is ok we can record in db and store
//reset fields == does not work
this.$refs['p' + index][0].fields.resetField()
//this.$refs['p' + index][0].resetFields();
// adding questions in db one by one
/*
axios
.post('http://127.0.0.1:8000/api/question_studies', element)
.then((result)=>{
console.log(result)
//add in the state
this.$store.commit("addQuestionSignaletique", element)
})
.catch(error => {
console.log("ERRRR:: ",error);
});
*/
}
}) //end loop foreach
}
}
};
Thanks a lot for help
EDIT AFTER THE FIRST ANSWER
Ok I didn't know. So I changed my mind : I added a "show" in my "data" which is true at the beginning. If everything is ok, I save the question and set the show to false.
The problem now is that when I have a question that is OK and the other one that is not. When I correct the question that was not ok and save it, BOTH questions go into the STATE. So there is a duplicate in my state AND my DB... What can I do? This is the code :
I just added this in the HTML :
<div v-for="(question, index) in questionsSignaletiques" :key="index" >
<a-form-model
layout="inline"
v-if="question.show"
class="blockQuestion"
>
...
data() {
return {
idStudy: this.$route.params.id,
aucuneQuestion:false,
questionsSignaletiques: [
{
"study":"/api/studies/" + this.$route.params.id,
"question":
{
type: "",
item: "",
multiple: false,
obligatoire: false,
inverse: false,
barometre: false,
originale: false,
signaletik: true,
choices: [{name:''}]
},
"error": {
message:"",
here:false
},
"show":true,
}
],
}
},
mounted() {
//retrieve question still recorded
axios
.get('http://127.0.0.1:8000/api/studies/' + this.idStudy + '/question_studies?question.signaletik=true')
.then((result)=>{
console.log(result.data["hydra:member"])
this.aucuneQuestion = result.data["hydra:member"].length === 0;
this.$store.commit("setListeQuestionsSignaletiques", result.data["hydra:member"])
})
.catch(err=>console.log(err))
},
methods: {
//adding a question
addItem () {
this.questionsSignaletiques.push(
{
"study":"/api/studies/" + this.idStudy,
"question":
{
type: "",
item: "",
multiple: false,
obligatoire: false,
inverse: false,
barometre: false,
originale: false,
signaletik: true,
choices: [{name:''}]
},
"error": {
message:"",
here:false
},
"show":true
}
)
},
//adding a choice
addChoice: function(choice) {
choice.question.choices.push({
name: ''
})
},
// submit the form
submit () {
this.questionsSignaletiques.forEach((element,index) =>
{
const inputType = element.question.type
const inputItem = element.question.item
const inputChoice = element.question.choices
for (const oneChoice of inputChoice)
{
if ((inputChoice.length == 1) ||(inputChoice.length == 2 && oneChoice.name == ""))
{
element.error.here=true
element.error.message = "You must have two choices at least"
return false; //on s'arrête là si il y a une erreur
}
else
{
console.log("no problem")
}
}
if (inputType == "" || inputItem =="")
{
element.error.here=true
element.error.message = "You must fill type and item"
}
else
{
// hide the question form
element.show =false
//adding in db
axios
.post('http://127.0.0.1:8000/api/question_studies', element)
.then((result)=>{
//add in the state
this.$store.commit("addQuestionSignaletique", element)
})
.catch(error => {
console.log("ERRRR:: ",error);
});
}
}) //end loop foreach
}
}
};
Thanks for help !
form.reset() does not work when using v-model.
Reset the reactive data instead.
reset() {
this.question.question.type = ""
...
...
}
In my registration form I have checkbox that confirms whether the user accepted the terms and conditions. The checkbox should validate once I hit the submit button, however since the checkbox is initially unselected, the validation error shows up straight away. Eventually, the error disappears reactively once I tick the checkbox, but for this particular scenario I would like to have the validation error show up only after I hit submit (if I did not check it). I'm not getting any particular console errors, but I'm simply getting stuck on the execution. Would anyone be able to show me how I can achieve this? I'd appreciate any help!
Checkbox.vue - this is the component representing the checkbox.
<template>
<div class="check-wrapper">
<label :for="id" class="check-label">
<input v-model="checkboxValue"
:id="id"
:checked="isCheckboxChecked"
:oninput="checkCheckbox()"
type="checkbox"
name="newsletter"/>
<span v-if="labelText && !isLabelHtmlText">{{ labelText }}</span>
<span v-if="labelText && isLabelHtmlText" class="label-html" v-html="labelText"></span>
<span :class="{'check-mark-error': checkboxError}" class="check-mark"></span>
</label>
<p v-if="checkboxError" class="checkbox-error text-error">{{checkboxError}}</p>
</div>
</template>
<script>
data: () => ({
checkboxValue: false
}),
methods: {
updateValue: function () {
if (this.$props.callback) {
this.$props.callback(this.$props.id, this.$props.checkboxData, this.checkboxValue);
}
},
checkCheckbox: function () {
this.updateValue();
}
}
</script>
Register.vue - this is the parent component where the registration takes place
<template>
<BasicCheckbox :id="'terms-privacy'"
:callback="onTermsClick"
:label-text="'terms and conditions'"
:is-label-html-text="true"
:checkbox-error="termsPrivacyError"
class="terms-privacy"/>
</template>
<script>
methods: {
validateData: function (data) {
if (!this.termsPrivacyError) {
this.sendRegistration(data).then(response => {
if (response) {
console.log('Registration successful');
this.loginUser({email: data.email, password: data.password}).then(response => {
if (response) {
console.log('User logged in!');
this.$router.push({name: ROUTE_NAMES_HOME.HOME});
}
})
}
});
}
},
// Terms and Privacy Checkbox
onTermsClick: function (checkboxId, checkboxData, data) {
this.termsPrivacyError = !data ? termsPrivacyErrorText : '';
},
}
</script>
First of all, this is not an elegant solution but it works, we use a computed value to control if the error should be displayed. We update it in submit method, and cancel it when we click it checkbox for demonstration purpose.
new Vue({
el: "#app",
data: {
termsState: false,
validated: false
},
computed: {
termsError() {
return this.validated && !this.termsState
}
},
methods: {
handleTermsState() {
this.validated = false
},
handleSubmit() {
this.validated = true
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'>
<label for="terms">
Terms and Privacy Policy
<input type="checkbox" id="terms" name="terms" v-model="termsState" #change="handleTermsState">
{{ termsState }}
</label>
<p style="color: red" class="for-error terms-error" v-if="termsError">You have to agree the terms and privacy condition.</p>
<div><button type="submit" #click="handleSubmit">Submit</button></div>
</div>
From your scenario, what I understood, the validation is not happening when the user didn't check privacy and policy. If the user ticks and unticks the checkbox, the validation is working.
If that's the case, what you can do is check the child component "Checkbox.vue" data property "checkboxValue" value, as the default value is already false, and it will be true if the user did the action and tick the checkbox. Just before submitting the form, add the checkboxValue condition check.
Here is the updated Register.vue component file:
<template>
<BasicCheckbox
:id="'terms-privacy'"
:callback="onTermsClick"
:label-text="'terms and conditions'"
:is-label-html-text="true"
ref="BasicCheckbox"
:checkbox-error="termsPrivacyError"
class="terms-privacy"
/>
</template>
<script>
methods: {
validateData: function (data) {
if (!this.termsPrivacyError && this.$refs.BasicCheckbox.checkboxValue) {
this.sendRegistration(data).then(response => {
if (response) {
console.log('Registration successful');
this.loginUser({email: data.email, password: data.password}).then(response => {
if (response) {
console.log('User logged in!');
this.$router.push({name: ROUTE_NAMES_HOME.HOME});
}
})
}
});
}
},
// Terms and Privacy Checkbox
onTermsClick: function (checkboxId, checkboxData, data) {
this.termsPrivacyError = !data ? termsPrivacyErrorText : '';
},
}
</script>
What I modified only:
I added the attribute of ref for the component stage `BasicCheckbox':
ref="BasicCheckbox"
And for the validation, I just only added condition whether the ref component 'BasicCheckbox' has value `true':
if (!this.termsPrivacyError && this.$refs.BasicCheckbox.checkboxValue)
I have some problems with mine Vue app.
I'm trying to validate login form that is connected with my Laravel App.
This is how template looks
<template>
<div>
<div class="main" v-if="canLogin">
<img class="logo" src="../assets/logo.png">
<form id="app"
#submit="checkForm"
method="post">
<p v-if="validation.length">
<b>Please correct the following error(s):</b>
<ul>
<li v-for="validation in validation">{{ error }}</li>
</ul>
</p>
<input class="form-input" type="email" v-model="form.email" id="email" align="center" placeholder="eMail" required>
<input class="form-input" type="password" v-model="form.password" id="password" align="center" placeholder="Password" required>
<button #click.prevent="login" class="submit">Sign In</button>
</form>
</div>
<div class="main" v-if="!canLogin">
<span> YOU ARE BLOCKED FOR 15 MINUTES</span>
</div>
</div>
</template>
As you see I want to foreach errors, but it's always giving error that
'validation' is defined but never used
And this is how mine script looks.
<script>
import User from "../apis/User";
export default {
data() {
return {
form: {
email: "",
password: ""
},
validation: [],
errors: '',
message: '',
canLogin: true,
};
},
mounted() {
User.canLogin().then(response => {
this.canLogin = response.data.canLogin;
});
},
methods: {
checkForm: function (e) {
this.errors = [];
if (!this.form.password) {
this.errors.push("Name required.");
}
if (!this.form.email) {
this.errors.push('Email required.');
} else if (!this.validEmail(this.email)) {
this.errors.push('Valid email required.');
}
if (!this.errors.length) {
return true;
}
e.preventDefault();
},
validEmail: function (email) {
var re = /^(([^<>()[\]\\.,;:\s#"]+(\.[^<>()[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
},
login() {
User.login(this.form)
.then(response => {
this.$store.commit("LOGIN", true);
localStorage.setItem("token", response.data.token);
this.$router.push({ name: "Dashboard" });
this.$snotify.success(response.data.message, {
timeout: 2000,
showProgressBar: true,
closeOnClick: true,
pauseOnHover: true
});
})
.catch(error => {
if (error.response.status === 400) {
this.errors = error.response.data.message;
this.$snotify.error(error.response.data.message, {
timeout: 2000,
showProgressBar: true,
closeOnClick: true,
pauseOnHover: true
});
}
if(error.response.status === 429){
this.canLogin = false;
}
});
}
}
};
</script>
I'm catching few thhings, like, canLogin, this is checking if IP is not blocked.
There is one more error like:
Elements in iteration expect to have 'v-bind:key' directives
I'm just a started with vue so don't judge me if it's simple fix.
BTW: without validation works fine, I believe it's not only problem with those errors and probbly I'm not catching some things as needed.
What am I doing wrong here?
Change
<ul>
<li v-for="validation in validation">{{ error }}</li>
</ul>
To:
<ul>
<li v-for="(error,index) in errors" v-bind:key="index">{{ error }}</li>
</ul>
In vue, you must provide a key for every v-for looping.
And change your data to:
data() {
return {
form: {
email: "",
password: ""
},
validation: [],
errors: [],
message: '',
canLogin: true,
};
},
I made your errors variable an arrayList.
I have a register form which works with Vue and local storage, when I submit the form blank or leave out an input the data is going to the local storage the same and not showing the HTML validation which is used by adding required attribute. Is there any way I can fix this problem by showing the HTML validation if the form has inputs which are empty or if the email do not have an at-sign inserted.
Form:
<form id="signup" method="post" v-on:submit.prevent>
<br>
<h1>Registration</h1>
<label for ="studentsorparents">Student or parents:</label>
<input type="text" id="studentsorparents" v-model="studentsorparents" required ="required">
<br><br>
<label for ="username">username:</label>
<input type="text" id="username" v-model="username" required ="required" v-text="null">
<br><br>
<label for="email">email: </label>
<input type="email" id="email" v-model='email' required ="required">
<br><br>
<label for="password">password: </label>
<input type="password" id="password" v-model='password' required ="required">
<br><br>
<button v-on:click='onSubmit' onclick="passuseremail()" >Register</button>
</form>
JS:
var signupApp = new Vue({
el: '#signup',
data: {
studentsorparents: '',
username: '',
email: '',
password: '',
},
methods: {
onSubmit: function () {
// check if the email already exists
var users = '';
var studentParent = this.studentsorparents;
var newUser = this.username;
var newEmail = this.email;
if (localStorage.getItem('users')) { // 'users' is an array of objects
users = JSON.parse(localStorage.getItem('users'));
}
if (users) {
if (users.some(function (user) {
return user.username === newUser
})) {
alert('Account already exits');
return;
}
if (users) {
if (users.some(function (user) {
return user.email === newEmail
})) {
alert('Account already exits');
return;
} else {
alert('Account created');
window.location.href = 'user-profile.html' + '#' + newUser;
}
}
users.push({
'studentsorparents': studentParent,
'username': newUser,
'email': newEmail,
'password': this.password
});
localStorage.setItem('users', JSON.stringify(users));
} else {
users = [{
'studentparents': studentParent,
'username': newUser,
'email': newEmail,
'password': this.password
}];
localStorage.setItem('users', JSON.stringify(users));
}
}
}
});
function passuseremail()
{
var username = document.getElementById('username').value;
localStorage.setItem("user-check", username);
var studentsorparents=document.getElementById('studentsorparents').value;
localStorage.setItem("students-parents-check", studentsorparents)
var email=document.getElementById('email').value;
localStorage.setItem("email-check", email)
return false
}
You need to add button type='submit' to the submit button else it will behave like just any other button.
<button v-on:click='onSubmit' onclick="passuseremail()" type="submit">Register</button>
It then only act as submit button else it will just trigger the button eventlisteners attached.
You have spaces after required attributes in your inputs:
required ="required"
It's incorrect and it will not work; just write it like this:
<input type=email id=email v-model=email required>
You can validate email like this:
const email_re = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;
if (email_re.test( email.value )) {
/* email is valid */
} else {
/* email is not valid */
}
You can add a class to the button like jsValidateRegister.
And the add the code
First declare a variable
isPageValid = true
Then in add the following code for validation so the isPageValid is set to false inside the passuseremail();
$(".jsValidateRegister").click(function ()
{
passuseremail();
});
In the onSubmit: function () check
isPageValid === true
I am implementing a very simple React login page. I have started with the following component, Account.
var Account = React.createClass({
getInitialState: function() {
return {
showSignUp: false,
showLogin: true
}
},
update: function(data) {
this.setState(data);
},
render: function() {
if(this.state.showSignUp) {
return <SignUp/>
}
else {
return <Login update={this.update}/>
}
}
});
As expected, the Login component is displayed and renders the following:
return (
<div>
<p><input type="text" placeholder={Language.languagePack.account.username} onChange={this.usernameChange}/></p>
<p><input type="password" placeholder={Language.languagePack.account.password} onChange={this.passwordChange}/></p>
<p><a onClick={this.performLogin}>{Language.languagePack.account.login}</a></p>
<p><a onClick={this.handleSignUp}>{Language.languagePack.account.signUp}</a></p>
<p>{failedMessage}</p>
</div>
)
This all works fine. The application is picking up on the changes via the onChange hook. If the user clicks "Sign Up" though, then the following code is called:
handleSignUp: function() {
this.props.update({showSignUp: true, showLogin: false})
},
Which calls the update method in the Account class, which updates the state and causes a re-render. This is what causes it to switch to the SignUp component.
return (
<div id="signUp">
<p><input type="text" placeholder={Language.languagePack.account.username} onChange={this.usernameChange} /></p>
<p><input type="password" placeholder={Language.languagePack.account.password} onChange={this.passwordChange} /></p>
<p><input type="email" placeholder={Language.languagePack.account.email} onChange={this.emailChange} /></p>
<p><a onClick={this.handleSignUp}>{Language.languagePack.account.signUp}</a></p>
</div>
)
And for some reason, none of the events are firing on this. onChange or onClick doesn't seem to be registered. I think this is related to my implementation of switching components based on a state change that renders different components. My question is, why is this happening and what part of React have I misunderstood to make this happen?
Full Classes
Login Component
var Login = React.createClass({
getInitialState: function() {
return {
username: '',
password: '',
failed: false
}
},
usernameChange: function(event) {
this.setState({
username: event.target.value,
failed: false
});
},
passwordChange: function(event) {
this.setState({
password: event.target.value,
failed: false
});
},
performLogin: function() {
var username = this.state.username;
var password = this.state.password;
console.log("Attempting login with username " + username + " and password " + password);
var _this = this;
Api.login(username, password, function(response) {
_this.props.update({user: response, loggedIn: true});
},
function(response) {
_this.setState({failed: true});
})
},
handleSignUp: function() {
this.props.update({showSignUp: true, showLogin: false})
},
render: function() {
var failedMessage = null;
if(this.state.failed) {
failedMessage = <div className="failed-auth">{Language.languagePack.account.invalidCredentials}</div>;
}
return (
<div>
<p><input type="text" placeholder={Language.languagePack.account.username} onChange={this.usernameChange}/></p>
<p><input type="password" placeholder={Language.languagePack.account.password} onChange={this.passwordChange}/></p>
<p><a onClick={this.performLogin}>{Language.languagePack.account.login}</a></p>
<p><a onClick={this.handleSignUp}>{Language.languagePack.account.signUp}</a></p>
<p>{failedMessage}</p>
</div>
)
}
});
Signup Component
var SignUp = React.createClass({
getInitialState : function() {
return {
username: '',
password: '',
email: ''
}
},
usernameChange: function(event) {
this.setState({
username: event.target.value
});
},
passwordChange: function(event) {
this.setState({
password: event.target.value
});
},
emailChange: function(event) {
this.setState({
email: event.target.value
});
},
handleSignUp : function() {
var username = this.state.username;
var password = this.state.password;
var email = this.state.email;
console.log("Signing up with username=" + username + " and password=" + password + "and email=" + email);
},
handleLogin : function() {
console.log("Fired!");
},
render: function () {
return (
<div id="signUp">
<p><input type="text" placeholder={Language.languagePack.account.username} onChange={this.usernameChange} /></p>
<p><input type="password" placeholder={Language.languagePack.account.password} onChange={this.passwordChange} /></p>
<p><input type="email" placeholder={Language.languagePack.account.email} onChange={this.emailChange} /></p>
<p><a onClick={this.handleSignUp}>{Language.languagePack.account.signUp}</a></p>
</div>
)
}
});
Your code does work; However, I did remove references to language.LanguagePack, since that's not defined in the code you provided. If you have a javascript error, it will prevent code from running.
https://jsfiddle.net/tqz3skcr/2/
var SignUp = React.createClass({
getInitialState : function() {
return {
username: '',
password: '',
email: ''
}
},
usernameChange: function(event) {
console.log('username Changed');
this.setState({
username: event.target.value
});
},
passwordChange: function(event) {
console.log('password Changed');
this.setState({
password: event.target.value
});
},
emailChange: function(event) {
console.log('email changed');
this.setState({
email: event.target.value
});
},
handleSignUp : function() {
var username = this.state.username;
var password = this.state.password;
var email = this.state.email;
console.log("Signing up with username=" + username + " and password=" + password + "and email=" + email);
},
handleLogin : function() {
console.log("Fired!");
},
render: function () {
return (
<div id="signUp">
<p><input type="text" onChange={this.usernameChange} /></p>
<p><input type="password" onChange={this.passwordChange} /></p>
<p><input type="email" onChange={this.emailChange} /></p>
<p><a onClick={this.handleSignUp}></a></p>
</div>
)
}
});
ReactDOM.render(
<SignUp />,
document.getElementById('container')
);
I don't see anything obvious but you could try this pattern to show/hide the components. Toggle showing and hiding components in ReactJs.
First of all, make your life easier and don't use indicators like:
{
showSignUp: true,
showLogin: false
}
something like this would be much simpler and would produce less errors:
{
formToShow: "signUpForm" // or "loginForm"
}
I would say, if you start coding in this way the issue will resolve by "clean code magic" ))