Search code examples
vue.jsvuejs3

Vue 3: Clear a input field value when a checkbox is checked


I have a form field that is an input text field and a checkbox. If the user types into the input field, then checks the checkbox I want to clear the input field so it's empty and the checkbox is checked. Vice versa, if the checkbox is checked then they start typing in the input field it should uncheck the checkbox.

With what I have at the moment when I look in Vue devtools I can see the input field being set to null when the checkbox is checked but in the browser the value is still showing in the input.

I have been upgrading the project from Vue 2 to Vue 3 so i'm wondering if its something I changed as it worked before.

Form.vue

<template xmlns="http://www.w3.org/1999/html">
    <div>
        <InputText
            name="answer_input"
            v-model="formRef.answer_input"
            :required="!formRef.answer_input_dont_know"
        >
            <template v-slot:question>
                {{ question }}
            </template>

            <template v-slot:input>
                <div class="form-group">Or</div>
                    <input
                        type="checkbox"
                        id="answer_input_dont_know"
                        v-model="formRef.answer_input_dont_know"
                    />
                    <label for="answer_input_dont_know" class="m-0 ml-2">
                        {{ label }}
                    </label>
            </template>
        </InputText>
    </div>
</template>

<script setup>
import InputText from "../Form/InputText";
import Form from "../../Form";
import { ref, markRaw, defineExpose, watch } from "vue";

const props = defineProps({
    formData: Object
})

let formRef = markRaw(ref(new Form({
    answer_input: null,
    answer_input_dont_know: false,
}, props.formData)))

watch(formRef.value.answer_input_dont_know, () => {
    if (formRef.value.answer_input_dont_know) {
        formRef.value.answer_input = null
 }
})

defineExpose({
 formRef
})
</script>

InputText.Vue

<template>
    <p v-if="$slots.question" class="input__question">
      <slot name="question"></slot>
    </p>

    <div class="form-group">
      <template>
        <input
          :name="name"
          type="text"
          class="form-control"
          v-model="model"
          :required="required"
        />
      </template>
    </div>

    <slot name="input"></slot>
</template>


<script setup>
const props = defineProps({
  name: String,
  value: String,
  required: Boolean
})
const model = defineModel()
</script>

Solution

  • watch(formRef.value.answer_input_dont_know, ...) is a mistake, it's the same as watch(false, ...), there is no way how it could be made reactive in JavaScript this way.

    It should be:

    watch(() => formRef.value.answer_input_dont_know, value => {
        if (value) {
            formRef.value.answer_input = null
     }
    })
    

    And there is no benefit in using markRaw on a ref in this case.