I've been converting my Vue3 app to smaller SFCs and I'm struggling to capture the click event on a button within the html page.
Before, I had my component with a template, but I've moved the template out of the component and into my webpage.
The problem is when I click the button, nothing happens. No error so it's like it doesn't know where to call the function.
index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3.2.37/dist/vue.esm-browser.prod.js",
"axios": "https://cdn.jsdelivr.net/npm/@bundled-es-modules/axios@0.27.2/axios.min.js",
"vue-demi": "https://cdn.jsdelivr.net/npm/vue-demi@0.14.10/+esm",
"vuelidatecore": "https://cdn.jsdelivr.net/npm/@vuelidate/core@2.0.3/+esm",
"vuelidatevalidators": "https://cdn.jsdelivr.net/npm/@vuelidate/validators@2.0.4/+esm",
}
}
</script>
<!-- <script defer type="module" src="./bootstrap.js"></script> -->
<link href="https://cdn.jsdelivr.net/npm/sweetalert2@11.15.10/dist/sweetalert2.min.css" rel="stylesheet">
</head>
<body>
<div id="newsletter-form">
<div class="input-group mb-3">
<input type="text" class="form-control text-white bg-transparent" placeholder="Enter your email" v-model="state.email" />
<div class="input-group-append">
<button class="btn btn-primary rounded-top-right-0" type="button" id="button-addon2" @click="recaptcha">Subscribe</button>
</div>
</div>
</div>
<script type="module">
import { createApp } from 'vue'
import NewsletterForm from './newsletter-form.js'
createApp(NewsletterForm).mount('#newsletter-form')
</script>
</body>
</html>
NewsletterForm
import { reactive } from 'vue'
import axios from 'axios';
import { useVuelidate } from 'vuelidatecore'
import { required, email, maxLength } from 'vuelidatevalidators'
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
export default {
setup () {
const state = reactive({
email: ''
})
const rules = {
email: { required, email, maxLength } // Matches state.contact.email
}
const v$ = useVuelidate(rules, state)
const recaptcha = async () => {
// Validate the form fields
const result = await v$.value.$validate()
if (!result) {
alert('sdfgsdg');
return
}
}
return { state, v$ }
},
template: '#newsletter-form'
}
Not sure exactly about the Vuelidate part, but this code looks like it's working well.
index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3.2.37/dist/vue.esm-browser.prod.js",
"axios": "https://cdn.jsdelivr.net/npm/@bundled-es-modules/axios@0.27.2/axios.min.js",
"vue-demi": "https://cdn.jsdelivr.net/npm/vue-demi@0.14.10/+esm",
"vuelidatecore": "https://cdn.jsdelivr.net/npm/@vuelidate/core@2.0.3/+esm",
"vuelidatevalidators": "https://cdn.jsdelivr.net/npm/@vuelidate/validators@2.0.4/+esm"
}
}
</script>
<!-- <script defer type="module" src="./bootstrap.js"></script> -->
<link href="https://cdn.jsdelivr.net/npm/sweetalert2@11.15.10/dist/sweetalert2.min.css" rel="stylesheet">
</head>
<body>
<div id="newsletter-form">
<div class="input-group mb-3">
<input type="text" class="form-control text-white bg-transparent" placeholder="Enter your email"
v-model="state.email" />
<div class="input-group-append">
<button class="btn btn-primary rounded-top-right-0" type="button" id="button-addon2"
@click="recaptcha">Subscribe</button>
<div>Email: {{ state.email }}</div>
</div>
</div>
</div>
<script type="module">
import { createApp } from 'vue'
import NewsletterForm from './newsletter-form.js'
createApp(NewsletterForm).mount('#newsletter-form')
</script>
</body>
</html>
newsletter-form.js
import { reactive } from 'vue'
import axios from 'axios';
import { useVuelidate } from 'vuelidatecore'
import { required, email, maxLength } from 'vuelidatevalidators'
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
export default {
setup() {
const state = reactive({
email: ''
})
const rules = {
email: { required, email, maxLength: maxLength(20) } // Matches state.contact.email
}
const v$ = useVuelidate(rules, state)
const recaptcha = async () => {
console.log('works here 👍🏻')
// Validate the form fields
const result = await v$.value.$validate()
console.log('result', result)
}
return { state, recaptcha, v$ }
}
}
The few changes I applied:
recaptcha
because it's not automatically returned because no script setup
maxLength(20)
to the validation, I'm not sure how it works tho so properly not the good way but it fixes the initial problemtemplate: '#newsletter-form'
because I don't think it was anyhow neededFew notes:
axios
can probably be skipped in favor of the browser's baked-in fetch
API