How to prevent default, then submit default with VueJS - vue.js

I am submitting a form using VueJS and i need to submit two actions on the final submit, one after the other.
Either one works when running just one.
What i am trying to do, is signup a user for firebase, wait, then submit the form with the same email/password as normal and signup that user with another sign in system.
The delimiters have been changed, so just over look that.
How to do this with Jquery
<form #submit="checkForm" #submit.prevent="register" action="#" method="post" novalidate="true" ref="form">
<h1 class="text-center">{{ 'customer.register.title' | t }}</h1>
<h1 v-if="authUser">
Is authed in
</h1>
<h1 v-else>
Not auth
</h1>
<div class="form-group">
<ul>
<li v-for="error in errors">
${ error }
</li>
</ul>
</div>
<p>
<label for="CustomerFirstName">${ firstName }</label>
<input id="name" v-model="name" type="name" name="customer[first_name]" autocomplete="name"
autocorrect="off" autocapitalize="off">
</p>
<p>
<label for="CustomerEmail">${ loginEmailName }</label>
<input id="email" v-model="email" type="email" name="customer[email]" autocomplete="email"
autocorrect="off" autocapitalize="off">
</p>
<p>
<label for="CustomerPassword">${ loginPasswordName }</label>
<input id="password" v-model="password" type="password" name="customer[password]">
</p>
<p>
<button type="submit" value="Create" class="btn btn-primary">Submit</button>
</p>
</form>
Then the JS that works on either one but not together.
const appTwo = new Vue({
delimiters: ["${", "}"],
el: "#create_customer_vue",
data: {
errors: ["1", "2", "3"],
email: '',
password: '',
name: null,
firstName: "First name",
loginEmailName: emailTitle,
loginPasswordName: passwordTitle,
title: registerTitle,
authUser: null
},
methods: {
register: function() {
firebase.auth().createUserWithEmailAndPassword(this.email, this.password)
},
submitForm: function(){
this.$refs.form.submit()
},
created() {
firebase.auth().onAuthStateChanged(user => { this.authUser = user })
},
checkForm: function(e) {
if (this.email && this.password) {
return true;
}
this.errors = [];
if (!this.email) {
this.errors.push("Valid email required");
}
if (!this.password) {
this.errors.push("Valid password required");
}
e.preventDefault();
}
}
});

Just call the one submit handler then submit the form normally after the Firebase operation completes.
For example
<form #submit.prevent="register" ... >
methods: {
checkForm () {
if (this.email && this.password) {
return true;
}
this.errors = [];
if (!this.email) {
this.errors.push("Valid email required");
}
if (!this.password) {
this.errors.push("Valid password required");
}
return false
},
async register ($event) {
if (this.checkForm()) {
await firebase.auth().createUserWithEmailAndPassword(this.email, this.password)
$event.target.submit() // or use this.$refs.form.submit() if you prefer
}
}
}

Related

Vue JS: Forms are not getting cleared when router.push() method is executed after the logout

I am using Flask as a backend and Vue JS as front end for my development. Vuex for state store.
In the logout() I am clearing the authentication token from localStorage via store.dispatch('/logout') and then using router.push('/login') to navigate to Login.vue. I find that the form details entered before are not getting cleared. When the logout() is performed it navigates to the Login.vue with flash message stating 'You have been logged out successfully'.
Below is the code snippet for the same:
logout() {
axios.get(`${this.host}:5000/logout`)
.then((res) => {
this.$store.dispatch('logout')
.then(() => {
this.$router.push('/login');
});
this.flashMessage.success({
message: res.data.msg,
time: 5000,
flashMessageStyle: {
backgroundColor: 'linear-gradient(#e66465, #9198e5)',
},
});
})
.catch((error) => {
this.flashMessage.error({
message: error.toString(),
time: 5000,
flashMessageStyle: {
backgroundColor: 'linear-gradient(#e66465, #9198e5)',
},
});
});
}
logout() is written in App.vue. Here router is an instance of vue-router.
To avoid the issue of form data not being cleared I have used router.go() instead of router.push() in the above code. But because of this implementation, the flash message is not getting displayed as the reload (because of router.go()) is overwriting the displaying of flash message which I don't want.
Please let me if it is possible to erase the form data after logout without getting into the trouble of not showing flash message.
Not sure how you have implemented Login.vue, but here is a Login.vue that I have implemented, and it works. One of the takeaways should be that my form model data values are initialized to empty strings.
<template>
<div id="login">
<form class="form-horizontal">
<div class="form-group">
<label for="username" class="col-md-offset-3 col-md-2 align-right">User Name</label>
<div class="col-md-3">
<input type="input" ref="username" class="form-control" id="username" v-model="username">
</div>
</div>
<div class="form-group">
<label for="password" class="col-md-offset-3 col-md-2 align-right">Password</label>
<div class="col-md-3">
<input type="password" class="form-control" id="password" v-model="password" v-on:keyup.enter="login">
</div>
</div>
<div class="form-group">
<div class="col-md-offset-5 col-md-4">
<button type="button" class="btn btn-default"
v-on:click="login">Login</button>
<span class="error-msg" v-if="errorMsg">{{ errorMsg }}</span>
</div>
</div>
</form>
</div>
</template>
<script>
import { loginUrl, axios, processAjaxLoginError } from '../globalvars.js'
export default {
name: 'Login',
data() {
return {
username: '',
password: '',
errorMsg: ''
}
},
methods: {
login() {
axios.post(loginUrl, {
username: this.username,
password: this.password
})
.then(response => {
// Commit the token to the store
this.$store.commit('updateToken', { token: response.data.message });
// Clear error message
this.errorMsg = '';
// Redirect to customer index view
this.$router.push("/customers")
})
.catch(error => {
this.errorMsg = processAjaxLoginError(error);
})
}
},
computed: {
token() {
return this.$store.state.token;
}
},
mounted() {
this.$refs.username.focus();
}
}
</script>

vform multiselected dropdown default selected and expected an array error

Can anyone help me I used Vform When I clicked edit button then it's show this error that expect array but I used already array in categories[] and also how to selected default category ?
I used vform and axios. I want to make a post with multiple category it's store successfully but when I click edit button then I get error that it's expected an array but I bind it an array and also how I make default select when it's edit mode ?
<form #submit.prevent="editMode ? updateVal() : createVal()">
<div class="modal-body">
<div class="form-group">
<label>Category</label>
<select class="form-control"
multiple
v-model="form.categories"
name="categories[]"
:class="{ 'is-invalid': form.errors.has('categories') }">
<option v-for="catetoryValue in getCategory" :key="catetoryValue.id" :value="catetoryValue.id">{{ catetoryValue.name }}</option>
</select>
<has-error :form="form" field="categories"></has-error>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button v-show="editMode" type="submit" class="btn btn-primary">Update</button>
<button v-show="!editMode" type="submit" class="btn btn-primary">Create</button>
</div>
</form>
<script>
export default {
data() {
return {
editMode: false,
categories:[],
selected: null,
form: new Form({
id: "",
title: "",
categories:[],
})
};
},
methods: {
getCategory(){
if (this.$gate.isAdminOrAuthor()) {
axios
.get("api/getcategory")
.then((response) => {
this.getCategory = response.data
})
.catch(() => {
console.log("Error...");
});
}
},
newModal() {
this.editMode = false;
this.form.reset();
$("#addnewmodal").modal("show");
},
edidModal(value) {
this.editMode = true;
this.form.reset();
$("#addnewmodal").modal("show");
this.form.fill(value);
},
},
created() {
this.getCategory();
},
};
</script>

#submit.prevent not working on vue md-input

when I click 'login button' even I don't fill data in md-input it still running,
I test my onSubmit() method by login with my user and it works!
I don't think I do thing wrong in the method so I guess that my form is incorrect.
here is my code :
my form
<form #submit.prevent="onSubmit">
<login-card header-color="green">
<h4 slot="title" class="title">CCRP Sign On</h4>
<p slot="description" class="description">IT solution by เจ้เก๋ IT-PM</p>
<md-field class="md-form-group" slot="inputs">
<md-icon>account_box</md-icon>
<label>ID...</label>
<md-input v-model.trim="userId" type="text"></md-input>
</md-field>
<md-field class="md-form-group" slot="inputs">
<md-icon>lock_outline</md-icon>
<label>Password...</label>
<md-input v-model.trim="password" type="password"></md-input>
</md-field>
<md-field class="md-form-group">
<md-icon>announcement</md-icon>
<label>Password...</label>
</md-field>
<md-button slot="footer" class="md-simple md-success md-lg" type="submit">Login</md-button>
</login-card>
</form>
in scrpit methods
async onSubmit() {
const authData = {
userId: this.userId,
password: this.password
};
await this.login(authData).then(() => {
if (this.isAuthenticated) {
this.$router.push("dashboard");
} else {
console.log("err");
}
});
},
can you help me solve this?
Your understanding of "prevent" key is quite incorrect.
All it does is not reload the form after submit action. However the submit action will be called irrespective of whether the prevent is used or not.
It is just preventing the default functionality of form getting reloaded after each submit.
On the other hand what you need to do is validate your form before actually submitting it.
Example :
//- Requires "vuelidate" - npm install vuelidate
<script>
import { validationMixin } from "vuelidate";
import { required, email } from "vuelidate/lib/validators";
export default {
name: "FormValidation",
mixins: [validationMixin],
data: () => ({
form: {
email: null,
password: null
},
userSaved: false,
sending: false,
lastUser: null
}),
validations: {
form: {
email: {
required,
email
},
password: {
required
}
}
},
methods: {
getValidationClass(fieldName) {
const field = this.$v.form[fieldName];
if (field) {
return {
"md-invalid": field.$invalid && field.$dirty
};
}
},
clearForm() {
this.$v.$reset();
this.form.email = null;
this.form.password = null;
},
saveUser() {
this.sending = true;
// Instead of this timeout, here you can call your API
window.setTimeout(() => {
this.lastUser = `${this.form.email}`;
this.userSaved = true;
this.sending = false;
this.clearForm();
}, 1500);
},
validateUser() {
this.$v.$touch();
if (!this.$v.$invalid) {
this.saveUser();
}
}
}
};
</script>
<style lang="scss" scoped>
.md-progress-bar {
position: absolute;
top: 0;
right: 0;
left: 0;
}
</style>
<template>
<div>
<!-- Calling validateUser insted of submit action -->
<form novalidate class="md-layout" #submit.prevent="validateUser">
<md-card class="md-layout-item md-size-50 md-small-size-100">
<!-- Title of the form -->
<md-card-header>
<div class="md-title">Login</div>
</md-card-header>
<!-- Inputs for the form -->
<md-card-content>
<md-field :class="getValidationClass('email')">
<label for="email">Email</label>
<md-input
type="email"
name="email"
id="email"
autocomplete="email"
v-model="form.email"
:disabled="sending"
/>
<span class="md-error" v-if="!$v.form.email.required">The email is required</span>
<span class="md-error" v-else-if="!$v.form.email.email">Invalid email</span>
</md-field>
<md-field :class="getValidationClass('password')">
<label for="password">Password</label>
<md-input
type="password"
name="password"
id="password"
autocomplete="password"
v-model="form.password"
:disabled="sending"
/>
<!-- to show errors in case validation fails -->
<span class="md-error" v-if="!$v.form.password.required">The email is required</span>
<span class="md-error" v-else-if="!$v.form.email.email">Invalid email</span>
</md-field>
</md-card-content>
<md-progress-bar md-mode="indeterminate" v-if="sending"/>
<md-card-actions>
<md-button type="submit" class="md-primary" :disabled="sending">Create user</md-button>
</md-card-actions>
</md-card>
<md-snackbar :md-active.sync="userSaved">The user {{ lastUser }} was saved with success!</md-snackbar>
</form>
</div>
</template>

Simple If return in VUE.JS method

Template won't show v-if when method return true.
I can log the username password and the failed attempt in the else section of my login method. If I try to log the loginFailed var I get loginFailed is not defined.
<template>
<div class="container-big">
<div class="container-header">
<h1>Our Login</h1>
</div>
<p v-if="loginFailed">
Login Failed
</p>
<div id="loginContainer" class="container-login">
<P>{{msg}}</p>
<input id="login" type="text" placeholder="username" v-model="username" spellcheck="false" >
<input id="key" type="password" placeholder="password" v-model="password" spellcheck="false" >
</div>
<div class="container-signin">
<button class="signin" id="go" #click="login()"></button>
</div>
</div>
</template>
<script>
export default {
name: 'Login',
data () {
return {
msg: 'This is your login',
password: '',
username: '',
loginFailed: false
}
},
methods: {
login () {
console.log(this.username);
console.log(this.password);
if (this.username !== '' && this.password === 'pass') {
this.$router.push( { name: 'dashboard', path: '/dashboard' }) }
else {
console.log('failed attempt')
this.loginFailed === true;
return this.loginFailed
}
}
}
}
</script>
What I want to do is if login failed show
<p v-if="loginFailed">
Login Failed
</p>
In the login() method, you're performing a comparison when you should actually assign a value to the loginFailed property:
this.loginFailed === true;
Change that line so that it actually assigns true to this.loginFailed:
this.loginFailed = true;
side note: You most likely don't need to return anything from login() since it's simply dealing with instance properties, you might want to remove this line:
return this.loginFailed

Click-to-Edit text field with Vue

I am working on Vue js and having an issue editing a field. When I click on a field to edit it, all the editable fields become active. Here is my code.
export default {
props: ['profileHeight'],
data() {
return {
User: User,
isEditing: false,
form:{
name:'',
email: '',
},
};
},
mounted() {
},
methods: {
activateInEditMode() {
this.isEditing = true
},
deActivateInEditMode() {
this.isEditing = false
}
}
}
<span>Profile settings</span>
<p>Full name<span v-on:click="activateInEditMode" v-show="!isEditing">{{User.state.auth.name}}</span>
<span v-show="isEditing" >
<input v-model="form.name" type="text" class="form-control" >
</span>
</p>
<p>E-mail<span>{{User.state.auth.email}}</span>
<span v-show="isEditing" >
<input v-model="form.email" type="text" class="form-control" >
</span>
</p>
Try using focus and blur methods to show/hide form elements!
Hope this helps!
new Vue({
el: '#app',
data(){
return {
user : {
name: '',
email: ''
},
editField : ''
}
},
methods : {
focusField(name){
this.editField = name;
},
blurField(){
this.editField = '';
},
showField(name){
return (this.user[name] == '' || this.editField == name)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
<h1>Profile settings</h1>
<label for="user-name">Full name</label>
<div class="field">
<span class="field-value" v-show="!showField('name')" #click="focusField('name')">{{user.name}}</span>
<input v-model="user.name" v-show="showField('name')" id="user-name" type="text" class="field-value form-control" #focus="focusField('name')" #blur="blurField">
</div>
<label for="user-email">Email address</label>
<div class="field">
<span class="field-value" v-show="!showField('email')" #click="focusField('email')">{{user.email}}</span>
<input v-model="user.email" v-show="showField('email')" type="email" class="field-value form-control" #focus="focusField('email')" #blur="blurField">
</div>
</div>
There are are dozens of ways to do this. I might recommend a component.
console.clear()
Vue.component("editable",{
props:["label", "value"],
template:`
<p>
{{label}}
<span #click="editing=true" v-show="!editing">
{{value}}
</span>
<span v-show="editing" >
<input :value="value"
#input="$emit('input', $event.target.value)"
#keydown.enter="editing=false"
type="text"
class="form-control" >
</span>
</p>
`,
data(){
return {
editing: false,
}
}
})
const User = {
name: 'bob',
email: 'bob#example.com'
}
new Vue({
el:"#app",
data() {
return {
form: User
};
},
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<span>Profile settings</span>
<editable label="Full name" v-model="form.name"></editable>
<editable label="E-mail" v-model="form.email"></editable>
<br>
{{form}}
</div>
I have written a component for this, I call it Click-to-Edit.
What it does:
Supports v-model
Saves changes on clicking elsewhere and on pressing Enter
ClickToEdit.vue:
<template>
<div>
<input type="text"
v-if="edit"
:value="valueLocal"
#blur.native="valueLocal = $event.target.value; edit = false; $emit('input', valueLocal);"
#keyup.enter.native="valueLocal = $event.target.value; edit = false; $emit('input', valueLocal);"
v-focus=""
/>
<p v-else="" #click="edit = true;">
{{valueLocal}}
</p>
</div>
</template>
<script>
export default {
props: ['value'],
data () {
return {
edit: false,
valueLocal: this.value
}
},
watch: {
value: function() {
this.valueLocal = this.value;
}
},
directives: {
focus: {
inserted (el) {
el.focus()
}
}
}
}
</script>