I want my input radio that is default checked to update the value in the v-model. But when I switch plan the v-model doesn't update dynamically. I'm stuck. Maybe I have to take a look at "watch" or "ref".
My formValues
is reactive and returns the good answer in the v-model. But when I switch plan... doesn't update the check output.
<template>
<!-- Second step -->
<section id="second-step">
<div class="row mt-4 px-2">
<div class="col-12">
<h1 class="h2 fw-bold">Select your plan</h1>
<p class="pt-1">
You have the option of monthly or yearly billing.
</p>
</div>
</div>
<!-- Form 2 -->
<form class="row justify-content-xl-between px-3 pe-xl-0" id="form-plan">
<!-- Plan 1 -->
<div class="col-12 col-xl plan mt-3 p-0">
<label for="arcade-plan" class="plan-label"></label>
<input v-model="check" type="radio" v-if="formValues.billing.monthly" :value="formValues.plan[0].name" name="plan" id="arcade-plan" checked>
<input v-model="check" type="radio" v-else="formValues.billing.yearly" :value="formValues.plan[1].name" name="plan" id="arcade-plan" checked>
<div class="plan-content card ps-2">
<div class="plan-icon mt-1">
<img src="assets/images/icon-arcade.svg" alt="">
</div>
<div class="plan-description">
<span class="plan-title mb-0">Arcade</span>
<div class="price monthly">
<div class="amount mb-0 fs-6 fw-medium text-cool-gray">$9/mo</div>
</div>
<div class="price yearly d-none">
<div class="amount fs-6 fw-medium text-cool-gray">$90/yr</div>
<div class="billing-msg text-primary">2 months free</div>
</div>
</div>
</div>
</div>
<!-- Plan 2 -->
<div class="col-12 col-xl plan mt-3 p-0">
<label for="advanced-plan" class="plan-label"></label>
<input v-model="check" type="radio" v-if="formValues.billing.monthly" :value="formValues.plan[2].name" name="plan" id="advanced-plan">
<input v-model="check" type="radio" v-else="formValues.billing.yearly" :value="formValues.plan[3].name" name="plan" id="advanced-plan">
<div class="plan-content card ps-2">
<div class="plan-icon mt-1">
<img src="assets/images/icon-advanced.svg" alt="">
</div>
<div class="plan-description">
<span class="plan-title mb-0">Advanced</span>
<div class="price monthly">
<div class="amount mb-0 fs-6 fw-medium text-cool-gray">$12/mo</div>
</div>
<div class="price yearly d-none">
<div class="amount fs-6 fw-medium text-cool-gray">$120/yr</div>
<div class="billing-msg text-primary">2 months free</div>
</div>
</div>
</div>
</div>
<!-- Plan 3 -->
<div class="col-12 col-xl plan mt-3 p-0">
<label for="pro-plan" class="plan-label"></label>
<input v-model="check" type="radio" v-if="formValues.billing.monthly" :value="formValues.plan[4].name" name="plan" id="pro-plan">
<input v-model="check" type="radio" v-else="formValues.billing.yearly" :value="formValues.plan[5].name" name="plan" id="pro-plan">
<div class="plan-content card ps-2">
<div class="plan-icon mt-1">
<img src="assets/images/icon-pro.svg" alt="">
</div>
<div class="plan-description">
<span class="plan-title mb-0">Pro</span>
<div class="price monthly">
<div class="amount mb-0 fs-6 fw-medium text-cool-gray">$15/mo</div>
</div>
<div class="price yearly d-none">
<div class="amount fs-6 fw-medium text-cool-gray">$150/yr</div>
<div class="billing-msg text-primary">2 months free</div>
</div>
</div>
</div>
</div>
<!-- Switch billing -->
<div class="col-12 py-3 rounded">
<div class="row bg-alabaster justify-content-center px-2">
<div class="col-10 col-sm-8 col-md-6">
<div class="switch-wrapper py-2 mb-0">
<input id="monthly" type="radio" name="switch" checked>
<input id="yearly" type="radio" name="switch">
<label id="billing-monthly" for="monthly" class="mx-sm-5">Monthly</label>
<label id="billing-yearly" for="yearly" class="mx-sm-5">Yearly</label>
<span class="toggler"></span>
</div>
</div>
</div>
</div>
</form>
</section>
<div class="container">
Selected :
{{ check }}
</div>
</template>
<script>
import { onMounted } from 'vue';
export default {
data() {
return {
check: 'Arcade (Monthly)'
}
},
props: {
step: Number,
formValues: Object
},
setup(props) {
onMounted(() => {
const switchInputs = document.querySelectorAll(".switch-wrapper input");
const prices = document.querySelectorAll(".price");
const toggleClass = "d-none";
/* Switch */
for (const switchInput of switchInputs) {
switchInput.addEventListener("input", function () {
for (const price of prices) {
price.classList.add(toggleClass);
}
const activePrices = document.querySelectorAll(
`.price.${switchInput.id}`
);
for (const activePrice of activePrices) {
activePrice.classList.remove(toggleClass);
}
/* Change billing type */
props.formValues.updateBilling()
console.log(props.formValues.billing.yearly)
})
}
})
}
}
</script>
I didn't find any sources about this problem yet. I think I can do something with a watch or ref.
Here is a very basic sample of Radio input binding with Vue:
const { createApp } = Vue;
const App = {
data() {
return {
check: 'Arcade (Monthly)',
items: ['Arcade (Monthly)', 'Advanced (Monthly)']
}
}
}
const app = createApp(App)
app.mount('#app')
<div id="app">
<div>Picked: {{ check }}</div><br />
<div v-for="(item, index) in items">
<input type="radio" :id="`item_${index}`" :value="item" v-model="check" />
<label :for="`item_${index}`">{{item}}</label>
</div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>