recaptcha model is blank vue.js - vue.js

Problem
loginForm.recaptcha is always blank. Am I missing anything?
Component
<template>
<div>
<vue-recaptcha v-model="loginForm.recaptcha"
sitekey="My key">
</vue-recaptcha>
</div>
</template>
<script>
export default {
data() {
return {
loginForm: {
recaptcha: ''
}
}
}
}
</script>
app.js
import VueRecaptcha from 'vue-recaptcha';
Vue.use(VeeValidate);
Vue.component('vue-recaptcha', VueRecaptcha);
I can confirm that the captcha is rendering successfully.

vue-recaptcha as no value/v-model property. You can use the verify event:
See demo JSFiddle here.
Code:
Vue.component('vue-recaptcha', VueRecaptcha);
new Vue({
el: '#app',
data: {
loginForm: {
recaptcha: ''
}
},
methods: {
recaptchaVerified(response) {
this.loginForm.recaptcha = response;
}
}
})
<script src="https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit" async defer>
</script>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-recaptcha#latest/dist/vue-recaptcha.js"></script>
<div id="app">
<div>
<vue-recaptcha #verify="recaptchaVerified"
sitekey="your key">
</vue-recaptcha>
</div>
loginForm: {{ loginForm }}
</div>

Related

Vue.js Toggle vuecomponents

I have a very simple Vue application I am building. I am new with using Vue.js. I have 2 vue components and I am trying to toggle between them with a button click. Can I use script code on the main page to toggle between the 2 vue components?
Here is my code. I assume I have to use v-show or v-if on the components or a div/span around the components to show and hide them.
App.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
<Display v-if="show" />
<button v-on:click="toggleDisplay()">toggle btn</button>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
import Display from './components/Display.vue'
export default {
name: 'App',
components: {
HelloWorld,
Display
},
data: {
return {
selectedComp: "HelloWorld"
}
},
methods: {
toggleDisplay(comp: string) {
this.selectedComp = comp;
}
}
}
</script>
Display.vue
<template>
<div class="post">
<div v-if="loading" class="loading">
Loading...
</div>
<div class="titleBlock text-center">
<div class="row justify-content-center" style="width:100%;">
<div class="col-6">
Service Title for Page
</div>
</div>
</div>
<div v-if="byteArray" class="content">
<img :src="byteArray" />
<div>{{ createImage }}</div>
<p>{{ byteArray }}</p>
</div>
</div>
</template>
<script lang="js">
import Vue from 'vue';
export default Vue.extend({
data() {
return {
loading: false,
post: null,
byteArray: null
};
},
created() {
this.fetchByteArray();
// Hide DisplayVue after 5 seconds
//setTimeout(() => this.byteArray = false, 5000)
//.then(
// setTimeout(() => this.byteArray = true, 2000)
// );
setTimeout(() => this.img = false, 5000)
.then(
setTimeout(() => this.img = true, 2000)
);
},
//watch: {
//}
methods: {
fetchByteArray() {
this.post = true;
this.byteArray = true;
this.loading = null;
fetch('https://localhost:5001/api/Doc/image001.png')
.then(response => response.json())
.then(bytes => {
this.byteArray = "data:image/png;base64," + bytes;
this.loading = false;
return;
})
.catch(console.log("Error"));
}
},
computed: {
createImage() {
return `<img class="img-fluid" src="data:image/png;base64,` + this.byteArray + `" />`;
}
}
});
</script>
Give a try to that one: https://vuejs.org/guide/essentials/component-basics.html#dynamic-components
Mainly like here: https://stackoverflow.com/a/73029625/8816585
<script setup>
import { ref } from "vue"
import Hehe from "#/components/Hehe.vue"
import Nice from "#/components/Nice.vue"
const boolean = ref(true)
</script>
<template>
<component :is="boolean ? Hehe : Nice" />
<button #click="boolean = !boolean">toggle</button>
</template>

Show on click / hide on blur wrapper component

I have several widgets that I'd like to toggle on click/blur/submit.
Let's take a simple example with an input (Vue 2 style)
Input.vue
<template>
<input
ref="input"
:value="value"
#input="input"
#blur="input"
#keyup.escape="close"
#keyup.enter="input"
/>
</template>
<script>
export default {
props: ['value'],
methods: {
input() {
this.$emit("input", this.$refs.text.value);
this.close();
},
close() {
this.$emit("close");
},
}
}
</script>
ToggleWrapper.vue
<template>
<div #click="open = true">
<div v-if="open">
<slot #close="open = false"></slot> <!-- Attempt to intercept the close event -->
</div>
</div>
</template>
<script>
export default {
data() {
return {
open: false,
}
},
}
</script>
Final usage:
<ToggleWrapper>
<Input v-model="myText" #submit="updateMyText" />
</ToggleWrapper>
So when I click on ToggleWrapper it appears, but if I close it, it doesn't disappear because it's not getting the close event.
Should I use scoped events ?
How can I intercept the close event by adding the less possible markup on the final usage ?
I think it makes sense to use a scoped slot to do this. But you can also try this kind of solution.
Input.vue
<template>
<input
ref="input"
:value="value"
#input="input"
#blur="input"
#keyup.escape="close"
#keyup.enter="input"
/>
</template>
<script>
export default {
props: ['value'],
methods: {
input() {
this.$emit("input", this.$refs.text.value);
this.close();
},
close() {
this.$parent.$emit('close-toggle')
},
}
}
</script>
ToggleWrapper.vue
<template>
<div #click="open = true">
Click
<div v-if="open">
<slot></slot> <!-- Attempt to intercept the close event -->
</div>
</div>
</template>
<script>
export default {
data() {
return {
open: false,
}
},
created() {
this.$on('close-toggle', function () {
this.open = false
})
}
}
</script>
In a Vue3 style, I would use provide and inject (dependency injection). This solution leaves the final markup very light and you still have a lot of control, see it below :
Final usage :
<script setup>
import { ref } from 'vue'
import ToggleWrapper from './ToggleWrapper.vue'
import Input from './Input.vue'
const myText = ref('hi')
const updateMyText = ($event) => {
myText.value = $event
}
</script>
<template>
<ToggleWrapper>
<Input :value="myText" #submit="updateMyText" />
</ToggleWrapper>
<p>value : {{myText}}</p>
</template>
ToggleWrapper.vue
<template>
<div #click="open = true">
<div v-if="open">
<slot></slot>
</div>
<span v-else>Open</span>
</div>
</template>
<script setup>
import { provide, inject, ref } from 'vue'
const open = ref(false)
provide('methods', {
close: () => open.value = false
})
</script>
Input.vue
<template>
<input
:value="value"
#input="input"
#blur="close"
#keyup.escape="close"
#keyup.enter="submit"
/>
</template>
<script setup>
import { inject, ref } from 'vue'
const props = defineProps(['value'])
const emit = defineEmits(['close', 'input', 'submit'])
const methods = inject('methods')
const value = ref(props.value)
const input = ($event) => {
value.value = $event.target.value
emit("input", $event.target.value);
}
const close = () => {
methods.close()
emit('close')
}
const submit = () => {
emit('submit', value.value)
close()
}
</script>
See it working here

How can I use vue.js environment variables like BASE_URL at CSS background: url(...)

I am trying to solve the challegene like
<template>
<div :style="{background: 'url($publicPath)img.gif'}"></div>
</template>
<script>
export default {
data() {
return {
publicPath: process.env.BASE_URL
}
}
}
</script>
but it doesn't work.
You can easily render the image using template string like:
<div :style="{background: `url(${publicPath}img.gif)`}"></div>
Demo:
new Vue({
el: "#myApp",
data() {
return {
publicPath: 'https://www.w3schools.com/html/'
}
}
})
.image { width:200px; height: 200px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
<div :style="{background: `url(${publicPath}pic_trulli.jpg)`}" class="image"></div>
</div>

How to use same template on different components in vue js?

Currently I am using as
<template> ... </template>
<script src="test1.js"> </script>
Where all my business logics are written in test1.js. Now I need to use test2.js with same template. I need to reuse the template with different component.
My current code goes like this...
common.vue
<template>
<div>
{{ page }}
</div>
<template>
<script src="../scripts/test1.js"></script>
Where in test1.js
export default {
name: 'home',
components: {
test: test
},
data() {
return {
page: "test1",
}
}
}
But also i need to use common.vue in my test2.js. Which i am not able to import both the .js seperately.
In angular we can write the fallowing late bindig which binds .html and .js(in ui.router)
.state('home', {
url:'/',
templateUrl: 'templates/home.html',
controller: 'HomeController'
})
Is there something similar to this?
You can share the template through the id attribute.
Vue.component('my-comp1', {
template: '#generic',
data () {
return {
text: 'I am component 1'
}
}
})
Vue.component('my-comp2', {
template: '#generic',
data () {
return {
text: 'I am component 2'
}
}
})
new Vue({
el: '#app'
})
<div id="app">
<my-comp1></my-comp1>
<my-comp2></my-comp2>
</div>
<template id="generic">
<div>
<p>{{ text }}</p>
</div>
</template>
<script src="https://unpkg.com/vue"></script>

Reusable nested VueJS components

Is it possible to declare a component inside another component in Vue.JS?
this is what i'm trying to do:
<!-- this is declared inside some-component.vue file -->
<script>
export default {
components:{
'cmptest' : {
template:'#cmptest',
props:['mprop']
}
},
data : () => ({
val:'world'
})
};
</script>
<template>
<div>
<template id="cmptest">
{{mprop}}
</template>
<cmptest mprop="hello"></cmptest>
<cmptest :mprop="val"></cmptest>
</div>
</template>
I'd like to avoid globally registering the child component if possible (with Vue.component(...))
In other words, I'd like to specify child's <template> inside the parent component file (without doing a huge line template:'entire-html-of-child-component-here')
Sure.
Like this:
https://jsfiddle.net/wostex/63t082p2/7/
<div id="app">
<app-child myprop="You"></app-child>
<app-child myprop="Me"></app-child>
<app-child myprop="World"></app-child>
</div>
<script type="text/x-template" id="app-child2">
<span style="color: red">{{ text }}</span>
</script>
<script type="text/x-template" id="app-child">
<div>{{ childData }} {{ myprop }} <app-child2 text="Again"></app-child2></div>
</script>
new Vue({
el: '#app',
components: {
'app-child': {
template: '#app-child',
props: ['myprop'],
data: function() {
return {
childData: 'Hello'
}
},
components: {
'app-child2': {
template: '#app-child2',
props: ['text']
}
}
}
}
});