2
votes

VueJS: utilisez v-model et: value en même temps

Je cherche un moyen d'utiliser v-model et : value en même temps sur le même objet.

J'ai eu cette erreur: p >

: value = "user.firstName" est en conflit avec v-model sur le même élément car ce dernier se développe déjà en une valeur liant en interne.

Le but est de définir comme valeur par défaut la valeur obtenue des mapGetters (provenant d'un magasin) et de définir la bonne valeur lorsque l'utilisateur soumettra la modification. (dans 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>


0 commentaires

3 Réponses :


1
votes

Vous ne devriez utiliser que v-model, cela créera une liaison bidirectionnelle avec la valeur de votre script: changer la variable dans js mettra à jour l'élément d'entrée, l'interaction avec l'élément d'entrée mettra à jour la variable.

Si vous souhaitez utiliser une valeur par défaut, définissez simplement la variable sur cette valeur (d'où qu'elle vienne).


0 commentaires

1
votes

La directive Vue v-model est un sucre syntaxique sur v-bind: value et v-on: input . Cet article sur alligator.io m'a beaucoup aidé à comprendre son fonctionnement.

Donc, fondamentalement, votre problème est que la directive v-model définit la valeur sur firstname , alors que vous définissez également explicitement value à user.firstName.

Il existe de nombreuses façons de gérer ce problème. Je pense qu'une solution rapide et simple consiste à stocker le firstname en tant que variable de données (comme vous le faites déjà), puis à utiliser uniquement v-model avec lui, sans tenir compte v-bind:value.

Ensuite, pour définir l'utilisateur du magasin pour le nom d'utilisateur par défaut, vous pouvez définir fristname comme nom d'utilisateur de l'utilisateur du magasin dans le hook créé :

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>


0 commentaires

3
votes

Généralement, vous voulez définir la valeur "initiale" du v-model sur l'objet lui-même, comme:

<script>
export default {
  data() {
    return {
      lang: "",

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

  // ...
}
</script>

Mais puisque vous l'obtenez depuis le magasin, vous pouvez accéder à l'objet getter spécifique avec this. $ store.getters [votre_objet] , donc je supprimerais la liaison : value et utiliserais v -modèle seul pour cela:

<div class="col-7">
  <input class="form-control m-input" type="text" v-model="firstname">
</div>
data() {
  return {
    firstname: 'someName'
  }
}


2 commentaires

Merci, ça marche maintenant. Je garderai à l'esprit que le meilleur choix est de déclarer une variable dans l'objet de données quelle que soit la valeur initiale


@wawanopoulos Pas de problème. Même si nous pourrions accéder directement aux objets du magasin, nous pourrions vraiment vouloir limiter la "portée" au composant actuel uniquement, car nous les utilisons comme un v-model ce qui signifie qu'ils sont sujets aux changements; et avec Vuex, nous ne pouvons probablement pas muter les états sans utiliser store.commit () .