Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS: Use v-model and :value in the same time

I'am searching a way to use v-model and :value in same time on the same object.

I got this error:

:value="user.firstName" conflicts with v-model on the same element because the latter already expands to a value binding internally.

The purpose is to set as default value the value get from the mapGetters (coming from one store) and to set the right value when the user will submit the modification. (in onSubmit)

<div class="form-group m-form__group row">
    <label for="example-text-input" class="col-2 col-form-label">
        {{ $t("firstname") }}
    </label>
    <div class="col-7">
        <input class="form-control m-input" type="text" v-model="firstname" :value="user.firstName">
    </div>
</div>


<script>
import { mapGetters, mapActions } from 'vuex';

export default {
    data () {
        return {
            lang: "",
            firstname: ""
        }
    },
    computed: mapGetters([
        'user'
    ]),
    methods: {
        ...mapActions([
            'updateUserProfile'
        ]),
        onChangeLanguage () {
            this.$i18n.locale = lang;
        },
        // Function called when user click on the "Save changes" btn
        onSubmit () {
            console.log('Component(Profile)::onSaveChanges() - called');
            const userData = {
                firstName: this.firstname
            }
            console.log('Component(Profile)::onSaveChanges() - called', userData);
            //this.updateUserProfile(userData);
        },
        // Function called when user click on the "Cancel" btn
        onCancel () {
            console.log('Component(Profile)::onCancel() - called');
            this.$router.go(-1);
        }
    }
}
</script>
like image 464
wawanopoulos Avatar asked Mar 06 '19 12:03

wawanopoulos


People also ask

Does Vue have 2 way binding?

Two-way binding is a powerful feature that, if used properly, can significantly speed up your development process. It reduces the complexity of keeping user input consistent with the application data model. In Vue, two-way binding is accomplished using the v-model directive.

What is the difference between value and v-model?

v-model is for two way bindings means: if you change input value, the bound data will be changed and vice versa. But v-bind:value is called one way binding that means: you can change input value by changing bound data but you can't change bound data by changing input value through the element.

Is Vue One way binding?

In Vue. js, we do not have to write a lot of lines to have two-way data binding, unlike other frameworks. One-way data binding means that the variable is just bound to the DOM.

What does v-model lazy do?

lazy. By default, v-model syncs with the state of the Vue instance (data properties) on every input event - which means every single time the value of our input changes. The . lazy modifier changes our v-model so it only syncs after change events.


3 Answers

Typically you want to set the "initial" value of the v-model on the object itself, like:

data() {
  return {
    firstname: 'someName'
  }
}

But since you're getting it from the store, you could access the specific getter object with this.$store.getters[your_object], so I would remove the :value binding and use v-model alone for this:

<div class="col-7">
  <input class="form-control m-input" type="text" v-model="firstname">
</div>
<script>
export default {
  data() {
    return {
      lang: "",

      firstname: this.$store.getters.user.firstName
    }
  },

  // ...
}
</script>
like image 84
Yom T. Avatar answered Sep 22 '22 01:09

Yom T.


The Vue v-model directive is syntactic sugar over v-bind:value and v-on:input. This alligator.io article helped me a lot to understand how it works.

So basically your problem is that the v-model directive sets value to firstname, while you're also explicitly setting value to user.firstName.

There are a lot of ways to handle this issue. I think a fast and straightforward solution is to store the firstname as a data variable (as you're already doing), and then use only v-model with it, disregarding v-bind:value.

Then, to set the user from the store for the default username, you could set fristname as the store user's username in the created hook:

script:

<script>
import { mapGetters, mapActions } from 'vuex';

export default {
    created() {
      this.firstname = this.user.username; // is this right? no used to the map getters syntax, but this is the idea
    },
    data () {
        return {
            lang: "",
            firstname: ""
        }
    },
    computed: mapGetters([
        'user'
    ]),
    methods: {
        ...mapActions([
            'updateUserProfile'
        ]),
        onChangeLanguage () {
            this.$i18n.locale = lang;
        },
        // Function called when user click on the "Save changes" btn
        onSubmit () {
            console.log('Component(Profile)::onSaveChanges() - called');
            const userData = {
                firstName: this.firstname
            }
            console.log('Component(Profile)::onSaveChanges() - called', userData);
            //this.updateUserProfile(userData);
        },
        // Function called when user click on the "Cancel" btn
        onCancel () {
            console.log('Component(Profile)::onCancel() - called');
            this.$router.go(-1);
        }
    }
}
</script>
like image 27
Sergeon Avatar answered Sep 19 '22 01:09

Sergeon


You should only use v-model, it will create a 2-way binding with the value in your script: changing the variable in js will update the input element, interacting with the input element will update the variable.

If you want to use a default value, just set the variable to that value (wherever it may come from).

like image 40
Eindbaas Avatar answered Sep 22 '22 01:09

Eindbaas