How to toggle between two components in vue.js? - javascript

i have two components Register.vue [my_reg-page]1and Login.vue [my-signin_page ]2, if the user opens register page in the browser (by using /register url), if the user clicks on the Login heading that user will be toggled into the login page(/login),similarly if the user opens login page over the chrome , if the user clicks on signup heading that user will be toggled into the registration-page, How to do toggling between two components,please help me to fix this issue.
Register.vue
<template>
<div class="main">
<div class="container">
<img id="side-img" src="../assets/sideImg.png" alt="notFound" />
<p id="side-content">Online Book Shopping</p>
<div class="box">
<div class="headings">
<h5 class="signin" id="login" :class="{ active: isLogin }" #click="isLogin = true">Login</h5>
<h5 class="signup" id="signup" :class="{ active: !isLogin }" #click="isLogin = false">signup</h5>
</div>
<form ref="myForm" #submit.prevent="handlesubmit">
<div class="fullname">
<p>FullName</p>
<input type="name" id="name-input" class="namebox" required v-model="fullName" autocomplete="off" pattern="[A-Za-z]{3,12}">
</div>
<div class="username">
<p>EmailID</p>
<input type="email" id="Email-input" class="emailbox" required v-model="email" pattern="^[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$">
</div>
<div class="password-section">
<p>Password</p>
<input :type="password_type" class="password" :class="{'password-visible': isPasswordVisible }" id="passField" v-model="password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$!%*?&])[A-Za-z\d#$!%*?&]{6,}$" required>
<i class="bi bi-eye-slash" id="togglePassword" #click="togglePassword();"></i>
</div>
<div class="mobile">
<p>MobileNumber</p>
<input type="tel" class="telephone" v-model="mobile" id="tel" pattern="^\d{10}$" required>
</div>
<button class="btn-section" id="btn" type="submit">Signup</button>
</form>
</div>
</div>
</div>
</template>
<script>
import service from '../service/User'
export default {
name: 'Register',
data() {
return {
fullName: '',
email: '',
password: '',
mobile: '',
password_type: "password",
isLogin:false,
isPasswordVisible: false,
title:'Online Book Shopping'
}
},
methods: {
togglePassword() {
this.password_type = this.password_type === 'password' ? 'text' : 'password'
this.isPasswordVisible = !this.isPasswordVisible
},
handlesubmit() {
let userData = {
fullName: this.fullName,
email: this.email,
password: this.password,
mobile: this.mobile
}
service.userRegister(userData).then(response => {
if (response.status == 201) {
alert("user registered successfully");
this.$refs.myForm.reset();
}
return response;
}).catch(error => {
alert("invalid credentials");
return error;
})
}
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/Register.scss";
</style>
Login.vue
<template>
<div class="main">
<div class="container">
<img id="side-img" src="../assets/sideImg.png" alt="notFound" />
<p id="side-content">Online Book Shopping</p>
<div class="box">
<div class="headings">
<h5 class="signin" id="login" #click="isLogin = true">Login</h5>
<h5 class="signup" id="signup" #click="isLogin = false">signup</h5>
</div>
<form ref="myForm">
<div class="username">
<p>EmailID</p>
<input type="email" id="Email-input" class="emailbox" autocomplete="off" required v-model="email" pattern="^[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$">
</div>
<div class="password-section">
<p>Password</p>
<input :type="password_type" class="password" :class="{'password-visible': isPasswordVisible}" id="passField" v-model="password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$!%*?&])[A-Za-z\d#$!%*?&]{6,}$" required>
<i class="bi bi-eye-slash" id="togglePassword" #click="togglePassword();"></i>
</div>
<div class="forget-section">
Forgot-password
</div>
<div class="btn-section">
<button type="submit" class="login-btn">Login</button>
</div>
<div class="seperator">
<h5><span>OR</span></h5>
</div>
<div class="btn-groups">
<button type="button" class="btn btn-primary">Facebook</button>
<button type="button" class="btn btn-light">Google</button>
</div>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Register',
data() {
return {
password_type: "password",
isPasswordVisible: false,
}
},
methods: {
togglePassword() {
this.password_type = this.password_type === 'password' ? 'text' : 'password'
this.isPasswordVisible = !this.isPasswordVisible
}
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/Login.scss";
</style>

Maybe I understood the question wrong. But you just want the user to be able to go to the registration page when on /login and the other way around.
You could just add add link in case you are using regular router.
<router-link to="/login">
<h5 class="signin" id="login" #click="isLogin = true">Login</h5>
</router-link>
<router-link to="/register">
<h5 class="signup" id="signup" :class="{ active: !isLogin }" #click="isLogin = false">signup</h5>
</router-link>

Use vue router https://router.vuejs.org/
Create a parent component LoginRegister.vue and include both of them in it
<template>
<div>
<login-form v-if="tab === 'login'" />
<register-form v-if="tab === 'register'" />
<button #click="tab = tab === 'register' ? 'login' : 'register'">Login/Register</button?
</div>
</template>
<script>
import LoginForm from "#/LoginForm";
import RegisterForm from "#/RegisterForm";
export default {
components: {
LoginForm,
RegisterForm,
},
data() {
return {
tab: 'login',
}
}
You could also have the buttons in the child components and use $emit to change the tab

Related

ReCaptcha not showing up

I'm trying to display a simple ReCaptcha. However, it appears if I delete onloadCallback function and then re-add it. Then it disappears until I do this again.
I will attach the code that I use. Also, I add localhost as a domain and I install the package using npm. I will write hidden instead of the site key that I use. Also, I want to hide my submit form button if the ReCaptcha is not verified, for this, I use useState hooks.
import React, { useState, useEffect } from 'react';
import ReCAPTCHA from "react-google-recaptcha";
import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import { collection, addDoc } from "firebase/firestore";
import {db} from "./firebase.js"
export default function Contact(){
const [captcha, setCaptcha] = useState(true);
const [formData, setFormData] = useState({
name: "",
phone: "",
subject: "",
message: ""
})
function handleOnChange(value){
setCaptcha(false);
console.log("recaptcha ", value);
}
function recaptchaLoaded() {
console.log('capcha successfully loaded');
}
function handleOnChange(value){
console.log("captcha value:" , value);
}
function handleChange(event){
const {name, phone, subject, message} = event.target
setFormData(prevFormData => ({
...prevFormData,
[event.target.name]: event.target.value
}))
}
function handleSubmit(event){
event.preventDefault();
try {
console.log(formData);
const docRef = addDoc(collection(db, "mesaje"), { formData });
console.log("Document written with ID: ", docRef.id);
} catch (e) {
console.error("Error adding document: ", e);
}
}
return(
<section id="contact" class="contact">
<div class="container">
<div class="section-title" data-aos="zoom-out">
<h2>Contact</h2>
<p>Date de contact</p>
</div>
<div class="row mt-5">
<div class="col-lg-4" data-aos="fade-right">
<div class="info">
<div class="address">
<i class="bi bi-geo-alt"></i>
<h4>Locatie:</h4>
<p>Galati</p>
</div>
<div class="email">
<i class="bi bi-envelope"></i>
<h4>Email:</h4>
<p>carageamarian72#yahoo.com</p>
</div>
<div class="phone">
<i class="bi bi-phone"></i>
<h4>Telefon:</h4>
<p>0744635351</p>
</div>
</div>
</div>
<div class="col-lg-8 mt-5 mt-lg-0" data-aos="fade-left">
<form onSubmit={handleSubmit} class="php-email-form" >
<div class="row">
<div class="col-md-6 form-group">
<input type="text" name="name" class="form-control" id="name" placeholder="Nume" required onChange={handleChange}
value={formData.name}/>
</div>
<div class="col-md-6 form-group mt-3 mt-md-0">
<input type="tel" class="form-control" name="phone" id="phone" placeholder="Telefon" required onChange={handleChange}
value={formData.phone} pattern="[0-9]{10}"/>
</div>
</div>
<div class="form-group mt-3">
<input type="text" class="form-control" name="subject" id="subject" placeholder="Subiect" required onChange={handleChange}
value={formData.subject}/>
</div>
<div class="form-group mt-3">
<textarea class="form-control" name="message" rows="5" placeholder="Mesaj" required onChange={handleChange}
value={formData.message}></textarea>
</div>
<div class="my-3">
<div class="loading">Loading</div>
<div class="error-message">Eroare, mesajul nu a fost trimis!</div>
<div class="sent-message">Mesajul a fost trimis, te vom contacta imediat!</div>
</div>
<ReCAPTCHA
sitekey="hidden"
onChange={handleOnChange}
onloadCallback={recaptchaLoaded}
/>
<div class="text-center"><button type="submit" disabled={captcha}>Trimite mesaj</button></div>
</form>
</div>
</div>
</div>
</section>
);
}
i found the problem. I had 2 different types of recaptcha in my html folder. They were in conflict.
I also delete the onloadCallback props.

Getting page to redirect to a new html file after entering correct login info?

I'm building a clone of the instagram login page for class and trying to figure out why my login page does not automatically re-direct to the feed (I've saved in another html file) after the correct login information is entered. I've googled several variations of how to write this in javascript but none have worked for me thus far.
My code:
const loginCombos = {
nat: 'natpass',
dog: 'dogpass',
cat: 'catpass',
clown: 'clownpass'
};
function validate() {
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
const userExists = loginCombos.hasOwnProperty(username)
const rightPass = loginCombos[username] === password
if (userExists && rightPass) {
alert('Login Successful');
window.location.replace('/feed.html');
return false;
} else {
alert('Sorry, your username or password was incorrect. Please double-check your login information and try again.')
return false;
}
}
<div class="container">
<div class="box">
<div class="heading"></div>
<form class="login-form" id="login" method="POST">
<div class="field">
<input id="username" type="text" placeholder="Phone number, username, or email"/>
<label for="username">Phone number, username, or email</label>
</div>
<div class="field">
<input id="password" type="password" placeholder="password"/>
<label for="password">Password</label>
</div>
<button class="login-button" title="login" onclick="validate()">Log In</button>
<div class="separator">
<div class="line"></div>
<p>OR</p>
<div class="line"></div>
</div>
<div class="other">
<button class="fb-login-btn" type="button">
<i class="fa fa-facebook-official fb-icon"></i>
<span class="">Log in with Facebook</span>
</button>
<a class="forgot-password" href="#">Forgot password?</a>
</div>
</form>
</div>
<div class="box">
<p>Don't have an account? <a class="signup" href="#">Sign Up</a></p>
</div>
</div>
You have to add onsubmit method in form element and make sure add event.preventDefault() method, here i provide you code. Please check what you did mistakes.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div class="container">
<div class="box">
<div class="heading"></div>
<form class="login-form" id="login" onsubmit="validate(event)">
<div class="field">
<input
id="username"
type="text"
placeholder="Phone number, username, or email"
/>
<label for="username">Phone number, username, or email</label>
</div>
<div class="field">
<input id="password" type="password" placeholder="password" />
<label for="password">Password</label>
</div>
<button class="login-button" title="login">Log In</button>
<div class="separator">
<div class="line"></div>
<p>OR</p>
<div class="line"></div>
</div>
<div class="other">
<button class="fb-login-btn" type="button">
<i class="fa fa-facebook-official fb-icon"></i>
<span class="">Log in with Facebook</span>
</button>
<a class="forgot-password" href="#">Forgot password?</a>
</div>
</form>
</div>
<div class="box">
<p>Don't have an account? <a class="signup" href="#">Sign Up</a></p>
</div>
</div>
</body>
<script src="script.js"></script>
</html>
script.js
const loginCombos = {
nat: "natpass",
dog: "dogpass",
cat: "catpass",
clown: "clownpass",
};
function validate(event) {
console.log("submit", event);
event.preventDefault();
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
const userExists = loginCombos.hasOwnProperty(username);
const rightPass = loginCombos[username] === password;
if (userExists && rightPass) {
alert("Login Successful");
window.location.href = "http://google.com";
} else {
alert(
"Sorry, your username or password was incorrect. Please double-check your login information and try again."
);
}
}
Try assigning direct path like, window.location = ./feed
const loginCombos = {
nat: 'natpass',
dog: 'dogpass',
cat: 'catpass',
clown: 'clownpass'
};
function validate() {
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
const userExists = loginCombos.hasOwnProperty(username)
const rightPass = loginCombos[username] === password
if (userExists && rightPass) {
alert('Login Successful');
window.location = '/feed.html';
return false;
} else {
alert('Sorry, your username or password was incorrect. Please double-check your login information and try again.')
return false;
}
}
<div class="container">
<div class="box">
<div class="heading"></div>
<form class="login-form" id="login" method="POST">
<div class="field">
<input id="username" type="text" placeholder="Phone number, username, or email"/>
<label for="username">Phone number, username, or email</label>
</div>
<div class="field">
<input id="password" type="password" placeholder="password"/>
<label for="password">Password</label>
</div>
<button class="login-button" title="login" onclick="validate()">Log In</button>
<div class="separator">
<div class="line"></div>
<p>OR</p>
<div class="line"></div>
</div>
<div class="other">
<button class="fb-login-btn" type="button">
<i class="fa fa-facebook-official fb-icon"></i>
<span class="">Log in with Facebook</span>
</button>
<a class="forgot-password" href="#">Forgot password?</a>
</div>
</form>
</div>
<div class="box">
<p>Don't have an account? <a class="signup" href="#">Sign Up</a></p>
</div>
</div>

same event emitting is happening just once instead of 2

the problem I have is that this.$emit is happening just once and I'm calling the event 2 times, I tried to figure it out but not luck so far, does somebody knows?
the idea behind is to emit and event and when the information is received then emit the event again to toggle the component
Form.vue
<template>
<div class="container">
<div class="row text-center">
<form>
<div class="form-group">
<div class="text-left">
<label for="username">Username</label>
<input type="text" id="username" class="form-control" v-model="username"/>
<label for="likes">Number of likes</label>
<input type="text" id="likes" class="form-control" v-model="likes"/>
</div>
</div>
<div class="form-group text-center">
<div class="row">
<div class="col-md-2 text-left">
<label>Bots available</label>
</div>
<div class="col-md-10">
<div class="pull-left">
<select>
<option>Bot 1</option>
</select>
</div>
</div>
</div>
</div>
<div class="pull-left">
<button class="btn btn-primary" #click.prevent="submit" :disabled="username.length == 0 || likes.length == 0 ">Start</button>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data(){
return{
username : '',
likes: ''
}
},
props:['loadingChange'],
methods:{
async submit(){
try {
this.$emit('loadingChange')
await axios.get('http://localhost:3000/botwork')
this.$emit('loadingChange')
} catch (error) {
console.log(error)
}
// console.log(this.username.length,this.likes.length)
}
}
};
</script>
<style>
</style>
App.vue
<template>
<div id="app">
<app-header></app-header>
<app-form v-if="!loading" #loadingChange='loading=!loading'></app-form>
<!-- <hr /> -->
<!-- <app-footer ></app-footer> -->
</div>
</template>
<script>
// import Footer from "./components/Footer.vue";
import Header from "./components/Header.vue";
import Form from "./components/Form.vue";
export default {
data(){
return{
loading: false
}
},
components: {
// appFooter: Footer,
appHeader: Header,
appForm: Form,
}
};
</script>
<style>
</style>

Make modal open after request - Vue.js

i have a register modal with vuejs and i need if user inserted the wrong information in the form and the information didn't validated in controller (using laravel) i could redirect user to the same page with modal open (i have "showRegister" in data and i need to make it open with "showRegister : true" after redirect)
new Vue({
el: '.LR-PC',
data: {
showRegister: false,
showLogin:false,
}
});
on default when we redirect to page showRegister is false
code:
<script type="text/x-template" id="modal-template">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<i class="fa fa-window-close" #click="$emit('close')" style="margin : 0 0 0 100%;"></i>
<slot name="header">
create user
</slot>
</div>
<div class="modal-body">
<slot name="body">
<form method="POST" action="{{ route('register') }}">
#csrf
<input class="input-style-1" type="text" name="name" id="name" maxlength="9"/>
<input class="input-style-1" type="text" name="f-name" id="f-name" maxlength="10"/>
<input class="input-style-1" type="email" name="email" maxlength="50">
<input name="password" class="input-style-1" type="password" maxlength="18">
<input type="password" name="password_confirmation" class="input-style-1" maxlength="18" onchange="hi(sa)">
<div class="r-phone-number input-style-1">
<input type="tel" name="phone" style="margin: 0px; border-width: 0px; width: 323px; text-align: right; position: relative; right: auto; left: 15px;" class="input-style-1">
<i class="fas fa-info-circle"></i>
</div>
#if($errors->any())
<div class="alert alert-danger">
<ul>
#foreach($errors as $error)
{{$error}}
#endforeach
</ul>
</div>
#endif
<slot name="footer">
<div class="modal-footer">
<button type="submit" class="btn btn-primary center-block wid-100">register</button>
</div>
</slot>
</form>
</slot>
</div>
</div>
</div>
</div>
</transition>
</script>
<a id="show-modal" #click="showRegister = true" class="l-main">register</a>
<modal v-if="showRegister" #close="showRegister = false">
</modal>
When you redirect back, pass an extra paramenter in view like: view('yourRoute', ['registerError'=>true]).
In your vue component receive it like <lr-pc register-error="{{$registerError}}"></lr-pc>. So you could handle it inside vue element.
new Vue({
el: '.LR-PC',
props:{
registerError:{
type:Boolean,
default: false
}
},
data: {
showRegister: this.registerError,
showLogin:false,
}
});
Of course, if you wish an inverse logic, use !this.registerError.

How do I pass data in $router.push in Vue.js?

I am creating an alert component for a CRUD app using Vue.js. I want a message to be passed to another component once data has been saved. Currently I am trying to pass this data in $router.push like this this.$router.push({path: '/', query: {alert: 'Customer Added'}}) Then access this data in another component. However this is not working as expected, instead the data is passed into the url.
This is the component which saves the data, Add.vue
<template>
<div class="add container">
<Alert v-if="alert" v-bind:message="alert" />
<h1 class="page-header">Add Customer</h1>
<form v-on:submit="addCustomer">
<div class="well">
<h4>Customer Info</h4>
<div class="form-group">
<label>First Name</label>
<input type="text" class="form-control" placeholder="First Name"
v-model="customer.first_name">
</div>
<div class="form-group">
<label>Last Name</label>
<input type="text" class="form-control" placeholder="Last Name"
v-model="customer.last_name">
</div>
</div>
<div class="well">
<h4>Customer Contact</h4>
<div class="form-group">
<label>Email</label>
<input type="text" class="form-control" placeholder="Email" v-model="customer.email">
</div>
<div class="form-group">
<label>Phone</label>
<input type="text" class="form-control" placeholder="Phone" v-model="customer.phone">
</div>
</div>
<div class="well">
<h4>Customer Location</h4>
<div class="form-group">
<label>Address</label>
<input type="text" class="form-control" placeholder="Address" v-model="customer.address">
</div>
<div class="form-group">
<label>City</label>
<input type="text" class="form-control" placeholder="City" v-model="customer.city">
</div>
<div class="form-group">
<label>State</label>
<input type="text" class="form-control" placeholder="State" v-model="customer.state">
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</template>
<script>
import Alert from './Alert'
export default {
name: 'add',
data () {
return {
customer: {},
alert:''
}
},
methods: {
addCustomer(e){
if(!this.customer.first_name || !this.customer.last_name ||
!this.customer.email){
this.alert = 'Please fill in all required fields';
} else {
let newCustomer = {
first_name: this.customer.first_name,
last_name: this.customer.last_name,
phone: this.customer.phone,
email: this.customer.email,
address: this.customer.address,
city: this.customer.city,
state: this.customer.state
}
this.$http.post('http://slimapp.dev/api/customer/add',
newCustomer)
.then(function(response){
this.$router.push({path: '/', query: {alert: 'Customer
Added'}})
});
e.preventDefault();
}
e.preventDefault();
}
},
components: {
Alert
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only
-->
<style scoped>
</style>
This the alert component, Alert.vue
<template>
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span></button>
{{message}}
</div>
</template>
<script>
export default {
name: 'alert',
props: ['message'],
data () {
return {
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
And this is the component where the alert is to be viewed, Customers.vue
<template>
<div class="customers container">
<Alert v-if="alert" v-bind:message="alert" />
<h1 class="page-header">Manage Customers</h1>
<table class="table table-striped">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="customer in customers">
<td>{{customer.first_name}}</td>
<td>{{customer.last_name}}</td>
<td>{{customer.email}}</td>
<td></td></tr>
</tbody>
</table>
</div>
</template>
<script>
import Alert from './Alert';
export default {
name: 'customers',
data () {
return {
customers: [],
alert: ''
}
},
methods: {
fetchCustomers(){
this.$http.get('http://slimapp.dev/api/customers')
.then(function(response){
this.customers = (response.body);
});
}
},
created: function(){
if (this.$route.params.alert) {
this.alert = $route.params.alert
}
this.fetchCustomers();
},
updated: function(){
this.fetchCustomers();
},
components: {
Alert
}
}
How do I solve this?
It is not possible to pass data through vue-router the way you want to. You only can pass parameters like this:
Route definition:
{ path: '/products/:id/edit', name: 'products.edit', component: ProductForm },
And then you can get the parameter with this.$route.params.id
Or you can do:
this.$router.push({name: 'products.index', params: { id: 1 }})
I suggest you to add a GET parameter like ?success=true or show an alert with sweetalert for example before pushing the new route.
A weird solution is to set the value to store/local_storage and retrieve and destroy it from the store/local_storage when the destination page loads.

Categories