Solution 1 :

All your <input> elements bind value to a different store getter, not the actual state. You didn’t post what your getters are and the error is likely there, but you say your state remains correct when you toggle the checkbox, so just bind your <input> elements to the actual state, i.e. use mapState instead of mapGetters. Even better, two-way bind your state with v-model on your <input> instead of the combination of :value + @input:

    <div class="mb-3 mt-3">
      <label for="postalCode" class="form-label">Code postal:</label>
      <input
        v-model="$store.state.fields.postalCode"
        type="text"
        class="form-control"
        id="postalCode"
        placeholder="Code Postal"
        name="POSTALCODE"
      />
    </div>
    <span style="color: red">{{ fieldErrors.postalCode }}</span>
    <div class="mb-3 mt-3">
      <input
        v-model="$store.state.fields.termsAndConditions"
        type="checkbox"
        class="me-1"
        id="chkTerms"
        placeholder="TERMS AND CONDITIONS"
        name="TERMS_AND_CONDITIONS"
      />
      <label for="chkTerms" class="form-label"
        >I accept the terms and conditions:</label
      >
      <span style="color: red">{{ fieldErrors.termsAndConditions}}</span>
    </div>

no onInputChange(), mapState, or even mutations needed

Solution 2 :

Did you console.log(element), what do you get there?

I am not sure but I think you need to pass the event to your function call

@input="onInputChange"($event)

Problem :

I have a form where all input fields are made reactive with an array of values in a Vuex store.

Here is the form :

    <form @submit="submitForm">
    <div class="mb-3">
        <label for="nom" class="form-label">Nom:</label>
        <input :value="nom" @input="onInputChange" type="text" class="form-control" id="nom" placeholder="Nom"
            name="NOM">
        <span style="color: red">{{ fieldErrors.nom }}</span>
    </div>
    <div class="mb-3">
        <label for="prenom" class="form-label">Prénom:</label>
        <input :value="prenom" @input="onInputChange" type="text" class="form-control" id="prenom"
            placeholder="Prénom" name="PRENOM">
        <span style="color: red">{{ fieldErrors.prenom }}</span>
    </div>
    <div class="mb-3 mt-3">
        <label for="email" class="form-label">Courriel:</label>
        <input :value="email" @input="onInputChange" type="text" class="form-control" id="email"
            placeholder="Email" name="EMAIL" />
        <span style="color: red">{{ fieldErrors.email }}</span>
    </div>
    <div class="mb-3 mt-3">
        <label for="phone" class="form-label">Téléphone:</label>
        <input :value="phone" @input="onInputChange" type="text" class="form-control" id="phone"
            placeholder="Numéro de téléphone" name="PHONE" />
        <span style="color: red">{{ fieldErrors.phone }}</span>
    </div>
    <div class="mb-3 mt-3">
        <label for="postalCode" class="form-label">Code postal:</label>
        <input :value="postalCode" @input="onInputChange" type="text" class="form-control" id="postalCode"
            placeholder="Code Postal" name="POSTALCODE" />
        <span style="color: red">{{ fieldErrors.postalCode }}</span>
    </div>
    <div class="mb-3 mt-3">
        <input :checked="termsAndConditions" @change="onInputChange" type="checkbox" class="me-1" id="chkTerms"
            placeholder="TERMS AND CONDITIONS" name="TERMS_AND_CONDITIONS" />
        <label for="chkTerms" class="form-label">I accept the terms and conditions:</label>
        <span style="color: red">{{ fieldErrors.termsAndConditions }}</span>
    </div>
</form>

All inputs share the same function (onInputChange) when there is a change to the value

Here are the computed properties used for the form as well as the function mentionned above:

    computed: {
    ...mapGetters(["nom", "prenom", "email", "phone", "postalCode", "termsAndConditions", "items"]),
},
methods: {
    onInputChange(evt) {
        const element = evt.target;
        const value =
            element.name === "TERMS_AND_CONDITIONS"
                ? element.checked
                : element.value;
        store.commit('UPDATE_'+element.name, value);
    },

As you can see, whenever there is a change in inputs, the appropriate mutation will be called from the store.

Here is the store and all the relevant mutations:

const state = {
    fields: {
        nom: '',
        prenom: '',
        email: '',
        termsAndConditions: false,
        phone:'',
        postalCode:'',
    },
}

    const mutations = {
        UPDATE_NOM(state, payload) {
            state.fields.nom = payload;
        },
        UPDATE_PRENOM(state, payload) {
            state.fields.prenom = payload;
        },
        UPDATE_EMAIL(state, payload) {
            state.fields.email = payload;
        },
        UPDATE_PHONE(state, payload){
            state.fields.phone = payload
        },
        UPDATE_POSTALCODE(state, payload){
            state.fields.postalCode = payload
        },
        UPDATE_TERMS_AND_CONDITIONS(state, payload) {
            state.fields.termsAndConditions = payload;
        },
    }

The problem is: Whenever there is a change in state on the checkbox, the values in the textboxes nom, phone and postalCode are cleared. Their corresponding values in the store stay the same though and the textboxes prenom and email don’t have their values cleared at all.

What is this behavior and why is it happenning?

Note: For reproduction sake, I am using bootstrap 5 so you might want to remove the classes if they cause a problem

Comments

Comment posted by Philippe Vermeulen

the use of mapState instead of mapGetter did indeed solve the problem of fields being cleared on other input changes, but it brought another problem during my validation step. The v-model works a wonder though and I’ll be able to remove some useless code now! Thanks a lot!

Comment posted by Philippe Vermeulen

I’d vote you up but I don’t have enough rep :’). Great answer, thanks for giving different alternatives.

Comment posted by Philippe Vermeulen

the event does get passed implicitely to the function as first argument and the evt.target inside the function does return the right element in use.

Comment posted by stackoverflow.com/questions/40956671/…

stackoverflow.com/questions/40956671/…

Comment posted by vuejs.org/guide/essentials/event-handling.html#method-handlers

This is clearly explained in the vue js 3 documentation 🙂

By esgsw