Example on 2-way binding on Vue3

The Brown BoxThe Brown Box
2 min read

I want to set a timer looks like below.

So I have set it up like below.

  1. Data type: TimeData.ts
export class TimeData {
  hours: number = 0;
  minutes: number = 0;
  seconds: number = 0;
}
  1. Set up the property as a model in the child component: SettingTime.vue
<template>
  <div class="q-pa-md">
    <q-card-section class="row q-gutter-md">
        <q-select
          class="my-select"
          v-model="model.hours"
          label="Hours"
          :options="hoursOptions"
          emit-value
          map-options
        />

        <q-select
        class="my-select"
          v-model="model.minutes"
          label="Minutes"
          :options="minutesOptions"
          emit-value
          map-options
        />

        <q-select
          class="my-select"
          v-model="model.seconds"
          label="Seconds"
          :options="secondsOptions"
          emit-value
          map-options
        />
      </q-card-section>
  </div>
</template>

<script setup lang="ts">
import type { TimeData } from './TimeData'

const model = defineModel<TimeData>({ required: true })

const hoursOptions = Array.from({ length: 24 }, (_, i) => ({ label: `${i}`, value: i }))
const minutesOptions = Array.from({ length: 60 }, (_, i) => ({ label: `${i}`, value: i }))
const secondsOptions = Array.from({ length: 60 }, (_, i) => ({ label: `${i}`, value: i }))



</script>

<style scoped>
.my-select {
  width: 80px;
}
</style>
  1. Inject the property of the Parent component as a model of the child component App.ts
<template>
 <div class="q-pa-md">
    <q-card>
      <q-card-section>
        <div class="text-h6">Set Countdown Time</div>
        <div class="text-body1"> {{ timeData.hours }}:{{ timeData.minutes }}:{{ timeData.seconds }} </div>
      </q-card-section>

      <SettingTime v-model="timeData" />
      <div> {{ stringTimeData }} </div>
      <q-card-actions align="right">
        <q-btn label="Start Countdown" color="primary" @click="handleStartCountdown" />
      </q-card-actions>
    </q-card>
  </div>



</template>

<script setup lang="ts">
import { ref, watch } from 'vue'
import SettingTime from './SettingTime.vue'
import { TimeData } from './TimeData'

const timeData = ref(new TimeData())
const stringTimeData = ref('')

const handleStartCountdown = () => {
  console.log('Start Countdown')
}


watch(timeData, (value) => {
  console.log('watch', JSON.stringify(value))
  stringTimeData.value = JSON.stringify(value)
})


</script>

ref: https://vuejs.org/guide/components/v-model

0
Subscribe to my newsletter

Read articles from The Brown Box directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

The Brown Box
The Brown Box