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>
Related
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.
<template>
<div class="hello">
<div class="heading">
</div>
<div class="row">
<div class="input-field col s6">
<div class="row">
<div class="input-field col s6 offset-s9">
<input v-model="blogs.Title" id="first_name" type="text" class="validate" placeholder="Title">
<input v-model="blogs.Name" id="first_name" type="text" class="validate" placeholder="Name">
</div>
<div class="input-field col offset-s6 s12">
<textarea v-model="blogs.content" id="textarea1" type="text" class="materialize-textarea s12" placeholder="Content of the blog" />
<a class="btn" #click.prevent="post">button</a>
</div>
</div>
</div>
</div>
<div class="blog">
<h1>{{blogs.Title}} </h1>
<h5 v-if="!blogs.Name =='' ">by</h5>
<h2 >{{blogs.Name}}</h2>
<h4 > {{blogs.content}}</h4>
</div>
<div class="blogposts">
<h1>Other posts and stories</h1>
<ul>
<li></li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'Main',
data(){
return{
blogs:{
Name:'',
Title:'',
content:''
},
blog:[{
}],
realBlogs:[{
}]
}
},
methods:{
post: function () {
this.blog.push(this.blogs)
this.$http.post('firebase',this.blog).then(function(data){
console.log(data.json());
},
this.blog = [{}]
);
}
},
created(){
this.$http.get('https://wbhspost-default-rtdb.firebaseio.com/posts.json').then(function(data){
return data.json();
}).then(function(data){
var blogsArray = [];
for (let key in data){
data[key].id = key
blogsArray.push(data[key]);
}
this.realBlogs = blogsArray;
})
}
}
</script>
Its like a blog. it just doesnt work.
This is all my code. Its all working fine besides retrieving data.
I am using firebase for the database and its good i just have no idea on how to retrieve the information that is stored there after the user submits it. I am also using vue js 2 if that matters to anyone.
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
I have the issue that the div in the v-if statement is not correctly working. If you run the server and the page when you click the button Sign Up it will briefly showing the div for signing up but it will get back the the original div in the first v-if statement after few seconds.
Instead I expect that it would show just show the div in the v-else because I am changing the boolean showSignUp with the v-on:click="signUp" which will call the function in the Vue App that will change the boolean.
This is the HTML :
<body onload="init()">
<!-- using the Vue App -->
<div id="app">
<!-- If it is not signed in just make it sign -->
<div v-if="!isLoggedIn" class="container-fluid">
<!-- Top Bar -->
<div class="row align-items-center justify-content-start">
<nav class="navbar navbar-light bg-light">
<h1>UST Computer Science Submission Tool</h1>
</nav>
</div>
<div class="row align-items-center justify-content-end">
<div v-if="!showSignUp">
<form class="getSpace" > <!-- SIGN IN FORM -->
<!-- Input fields -->
<div class="form-group">
<label for="inputEmail">Email address</label>
<input type="email" class="form-control" id="inputEmail">
</div>
<div class="form-group">
<label for="inputPassword">Password</label>
<input type="password" class="form-control" id="inputPassword">
</div>
<!-- Buttons -->
<button v-on:click="signIn" class="btn btn-primary">Sign In</button>
<button v-on:click="signUp" class="btn btn-primary">Sign Up</button>
</form>
</div>
<div v-if="showSignUp">
<form class="getSpace"> <!-- SIGN UP FORM -->
<!-- Input fields -->
<div class="form-group">
<label for="inputEmail">Email address</label>
<input type="email" class="form-control" id="singUpEmail">
</div>
<div class="form-group">
<label for="inputPassword">Password</label>
<input type="password" class="form-control" id="singUpInputPassword">
</div>
<!-- Buttons -->
<button v-on:click="submitRegistration" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
<!-- Else is already signed in -->
<div v-else class="container-fluid">
<div class="row">
<div class="col">You did it</div>
<div class="col"></div>
</div>
</div>
</div>
</body>
This is the JS for the Vue App:
let app
// On loading page
function init() {
app = new Vue({
el: '#app',
data: {
email: '',
password: '',
isLoggedIn: false,
showSignUp: false
},
methods: {
signIn: signIn,
signUp: signUp,
submitRegistration: submitRegistration,
}
});
}
// methods
function signIn(event) { // when clicked Sing In button
// check before in the data base if it is correct
// Now show the Users page
app.isLoggedIn = !app.isLoggedIn;
}
function signUp (event) { // when clicked Sing Up button
// This will change the form
console.log('was here');
app.showSignUp = true;
}
function submitRegistration (event) {
console.log(event);
// Call http
}
you need to prevent the action
<button v-on:click.prevent="signUp" class="btn btn-primary">Sign Up</button>
Well, this is the component where I'm trying to create all the content. It is a crud that saves the data when and what I want is for the modal to disappear.
<div class="container">
<div class="table-wrapper">
<div class="table-title">
<div class="row">
<div class="col-sm-6">
<h2>Codigos De <b>Acceso.</b></h2>
</div>
<div class="col-sm-6">
<i class="material-icons"></i> <span>Agregar nuevo codigo</span>
</div>
</div>
</div>
<div class='col-sm-12 pull-right d-flex flex-row-reverse'>
<div id="custom-search-input">
<div class="input-group">
<input type="text" class="form-control" placeholder="Buscar" aria-label="Input group example" aria-describedby="btnGroupAddon2">
<div class="input-group-append">
<button class="btn btn-primary" id="btnGroupAddon2"><i class="fas fa-search"></i></button>
</div>
</div>
</div>
</div>
<div class='clearfix'></div>
<hr>
<div id="loader"></div>
<div id="resultados"></div>
<div class='outer_div'></div>
</div>
</div>
<!-- Add Modal HTML -->
<div id="addProductModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<form #dataForm="ngForm" (ngSubmit)="addData(dataForm)">
<div class="modal-header">
<h4 class="modal-title">Añadir Codigo</h4>
<button type="button" class="close" data-dismiss="modal" id="dismiss" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Código</label>
<input type="text" name="code" class="form-control" #code="ngModel" [(ngModel)]="dataService.selectedData.code" required >
</div>
<div class="form-group">
<label>Dirección</label>
<input type="text" name="direction" class="form-control" #direction="ngModel" [(ngModel)]="dataService.selectedData.direction" required>
</div>
<div class="form-group">
<label>Comentario</label>
<input type="text" name="comment" class="form-control" #comment="ngModel" [(ngModel)]="dataService.selectedData.comment" required>
</div>
<div class="form-group">
<label>Tech #</label>
<input type="number" name="tech" class="form-control" #tech="ngModel" [(ngModel)]="dataService.selectedData.tech" required>
</div>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-secondary" data-dismiss="modal" value="Cancelar">
<input type="submit" class="btn btn-primary" value="Guardar datos">
</div>
</form>
</div>
</div>
</div>
<div class="center">
and this is my ts file:
import { Component, OnInit } from '#angular/core';
import { Data } from '../../models/data' // La ruta puede ser distinta.
import { DataService } from '../../services/data.service';
import { NgForm } from '#angular/forms';
#Component({
selector: 'app-datas',
templateUrl: './datas.component.html',
styleUrls: ['./datas.component.css'],
providers: [DataService]
})
export class DatasComponent implements OnInit {
constructor(private dataService: DataService) { }
ngOnInit() {}
addData(form: NgForm) {
this.dataService.postData(form.value)
.subscribe(res => {
this.resetForm(form);
})
}
/*
close(form?: NgForm){
if
}*/
resetForm(form?: NgForm) {
if(form){
form.reset();
var dismiss = document.querySelector('#addProductModal');
console.log(dismiss);
this.dataService.selectedData = new Data();
}
}
}
As you can see, that last method is called resetForm, I tried to clean the form when the data is sent and I have achieved it, but what I need is that the modal is discarded. Anyone have an idea?
NPM uninstall jQuery right away. Don't use the JavaScript version of bootstrap, install ngx-bootstrap and use the Angular components. They play much nicer with Angular. Your component should not be inspecting the DOM with querySelector and you shouldn't use any jQuery. If you rewrite the component using ngx-bootstrap you will be able to get an instance of an Angular modal component and call close.
https://valor-software.com/ngx-bootstrap/#/modals