I have this function that returns either true or false that is created in a child component. And this child component is called inside a nuxt page. It’s like this:
Child component
<template>
<div>
<h2 class="font-bold text-2xl text-white">Select Your Role</h2>
<p class="text-gray-90 my-2">
Select your role that fit most with your needs
</p>
<div>
<div class="flex gap-3">
<div
class="flex items-center gap-3 border border-dark-60 p-3 rounded-lg"
>
<label class="cursor-pointer" for="1">SEO Specialist</label>
<input
id="1"
v-model="selectedRole"
class="opacity-60"
type="radio"
value="SEO Specialist"
/>
</div>
<div
class="flex items-center gap-3 border border-dark-60 p-3 rounded-lg"
>
<label for="2">Content Writer</label>
<input
id="2"
v-model="selectedRole"
class="opacity-60"
type="radio"
value="Content Writer"
/>
</div>
<div
class="flex items-center gap-3 border border-dark-60 p-3 rounded-lg"
>
<label for="3">Product Manager</label>
<input
id="3"
v-model="selectedRole"
class="opacity-60"
type="radio"
value="Product Manager"
/>
</div>
</div>
<div class="flex gap-3 my-3">
<div
class="flex items-center gap-3 border border-dark-60 p-3 rounded-lg"
>
<label for="4">Business Owner</label>
<input
id="4"
v-model="selectedRole"
class="opacity-60"
type="radio"
value="Business Owner"
/>
</div>
<div
class="flex items-center gap-3 border border-dark-60 p-3 rounded-lg"
>
<label for="5">Freelancer</label>
<input
id="5"
v-model="selectedRole"
class="opacity-60"
type="radio"
value="Freelancer"
/>
</div>
<div
class="flex items-center gap-3 border border-dark-60 p-3 rounded-lg"
>
<label for="6">SEO / Marketing Agency</label>
<input
id="6"
v-model="selectedRole"
class="opacity-60"
type="radio"
value="SEO / Marketing Agency"
/>
</div>
</div>
<div class="flex gap-3">
<div
class="flex items-center gap-3 border border-dark-60 p-3 rounded-lg"
>
<label for="7">Product Marketing Manager</label>
<input
id="7"
v-model="selectedRole"
class="opacity-60"
type="radio"
value="Product Marketing Manager"
/>
</div>
<div
class="flex items-center gap-3 border border-dark-60 p-3 rounded-lg"
>
<cm-input placeholder="Other"></cm-input>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SelectPosition',
data() {
return {
selectedRole: '',
otherRole: '',
}
},
methods: {
methods: {
isValid() {
this.$emit('update:valid', false)
},
},
},
}
</script>
Page file as parent
<template>
<div class="w-full">
<div class="flex flex-col">
<div class="container grid grid-cols-12 gap-8 mx-auto p-12">
<div class="col-span-3"></div>
<div class="col-span-6">
<h1 class="font-bold text-3xl text-white">Setting Up the Crawler</h1>
<p class="text-gray-60 col-span-6">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Tempora
maiores suscipit doloremque!
</p>
</div>
</div>
<RegisterProgressBar :value="step" :max="5" />
<div class="container grid grid-cols-12 gap-8 mx-auto p-12">
<div class="col-span-3 gap-20 mx-3">
<transition name="fade-in" mode="out-in">
<div
class="flex flex-col gap-4 border border-dark-60 rounded-lg h-[200px] max-h-48 items-center mx-11"
>
<img
src="https://www.gravatar.com/avatar/078a5f992a23c763d83473ebeb359c6d.jpg?d=identicon&s=200"
width="40"
height="40"
alt="team picture"
class="mt-3"
/>
<div class="flex flex-col items-center gap-1">
<h3 class="text-lg font-bold">{{ team_name }}</h3>
<p>{{ domain_label }}</p>
</div>
<cm-tooltip>
<template #toggler>
<span class="underline"> What's this? </span>
</template>
<span class="dark:text-dark-80">
This is a pre-defined team name for you. You can change the
name later in the settings.
</span>
</cm-tooltip>
<div
v-if="keywords.length !== 0"
class="flex justify-center rounded-lg p-4 mt-3 bg-dark-90 text-gray-60 w-full text-left"
>
<div class="flex flex-col gap-1 text-left">
<div>
<cm-icon class="bx bx-key" />
<span class="mx-3 underline">Keywords</span>
<span class="font-bold">{{ keywords.length }}</span>
</div>
<div v-if="selectedCountry.length !== 0">
<cm-icon class="bx bx-building" />
<span class="mx-3 underline">Countries</span>
<span class="font-bold">{{ selectedCountry.length }}</span>
</div>
<div v-if="selectedLanguage.length !== 0">
<cm-icon class="bx bx-user-voice" />
<span class="mx-3 underline">Languages</span>
<span class="font-bold">{{ selectedLanguage.length }}</span>
</div>
<div v-if="device.length !== 0">
<cm-icon class="bx bx-devices" />
<span class="mx-3 underline">Devices</span>
<span class="font-bold">{{ device.length }}</span>
</div>
</div>
</div>
</div>
</transition>
</div>
<div class="flex flex-col col-span-6">
<transition name="fade-in" mode="out-in">
<component :is="currentStepComponent" />
</transition>
<div class="flex gap-3 self-end mt-3">
<cm-button v-if="step > 1" variant="gray" contextual @click="back"
>Prev</cm-button
>
<cm-button variant="gray" :disabled="isValid">Next</cm-button>
</div>
</div>
<div class="col-span-3"></div>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import appConfig from '~/config/globals/appConfig'
import RegisterProgressBar from '~/components/new-register/ProgressBar.vue'
import SelectPosition from '~/components/new-register/SelectPosition.vue'
import SelectPlan from '~/components/new-register/SelectPlan.vue'
export default {
name: 'UserPosition',
auth: 'guest',
components: {
RegisterProgressBar,
SelectPosition,
SelectPlan,
},
layout: 'new-register/default2',
data() {
return {
team_name: JSON.parse(localStorage.getItem('app.registration.data'))
.team_name,
domain_label: JSON.parse(localStorage.getItem('app.registration.data'))
.domain_label,
step: 2,
}
},
computed: {
...mapState('registration', {
domain: 'domain',
keywords: 'keywords',
selectedLanguage: 'selectedLanguage',
selectedCountry: 'selectedCountry',
device: 'device',
}),
currentStepComponent() {
switch (this.step) {
case 1:
return 'SelectPosition'
case 2:
return 'SelectPosition'
case 3:
return 'SelectPlan'
case 4:
return 'SelectLanguage'
case 5:
return 'SelectDevice'
default:
return ''
}
},
},
methods: {
back() {
this.step--
},
next() {
this.step++
this.submit()
},
submit() {
try {
console.log({
...this.registrationData,
position: 'selectedRole',
})
this.$storage.setUniversal(appConfig.app.registration, {
...this.registrationData,
position: 'selectedRole',
})
this.$cmToast({
title: 'Data stored successfully!',
icon: 'bx-info-circle',
variant: 'success',
})
} finally {
this.isLoading = false
}
},
},
}
</script>
In short I want to make the next button to be disabled if both selectedRole and otherRole data is empty string.
2
Answers
You have to take this custom-event on child component like and also I think you should name your custom event as
updateValid
and also from button component your value inupdate:valid
is undefined you must pass a correct valueand after this you can create a method also I’m guessing you want change the value of
isValid
so you can do that in this funcI didn’t solve this one, but I figured another way by using vuex instead of props.