0

I create dynamic component using Vue and Bootstrap Tokenfield. But v-model doesn't work in this case.

Assume, I have an array below:

index variant_options
1 aaa
2 sss

When I remove index 1, the result of index 1 should be "sss" but still "aaa"

<div class="card" v-for="(variant, index) in form.variants" :key="index">
<div class="card-body"> <span class="float-right" style="cursor: pointer" @click="deleteVariant(index)">
                                                            X
                                                        </span>
    <div class="row">
        <div class="col-md-4">
            <label for="weight">Variant Type {{ index + 1 }} </label>
            <div class="input-group">
                <input type="text" id="variant_type" class="form-control" v-model="
                                                                            variant.variant_type
                                                                        " @keyup="tokenField()" placeholder="Input variant type. E.g: Color" name="name" required autofocus /> </div>
        </div>
        <div class="col-md-8">
            <label for="weight">Variant Options {{ index + 1 }}</label>
            <div class="input-group">
                <input type="text" id="variant_options" autofocus="true" v-model="
                                                                            variant.variant_options
                                                                        " @mouseover="
                                                                            tokenField()
                                                                        " placeholder="Input variant options. E.g: Blue, Brown," class="
                                                                            form-control
                                                                            variant_options
                                                                        " /> </div>
data() {
    return {
        form: new Form({
            variants: [
                {
                    variant_type: '',
                    variant_options: '',
                },
            ],
        }),
    };
},
methods: {
    tokenField() {
        $('.variant_options').tokenfield({
            showAutocompleteOnFocus: true,
        });
    },
    addVariant() {
        if (this.form.variants.length <= 1) {
            this.form.variants.push({
                variant_type: '',
                variant_options: '',
            });
        } else {
            this.error = 'You can only add 2 type of varians';
            $('#errMsg').show();
        }
    },
    deleteVariant(index) {
        this.form.variants.splice(index, 1);
        $('#errMsg').hide();
    },
}, // methods:
Cheer Up
  • 53
  • 1
  • 6
  • @CheerUp Your code is incomplete. Please provide the full code. – StevenSiebert Aug 28 '21 at 08:05
  • Is there any reason for the `new Form({` bit in the `data()` code? – José A. Zapata Aug 28 '21 at 08:11
  • @Fabalance: What do you mean incomplete? What part do you need? What is missing part? Just tell me. I think, I've write all of code. – Cheer Up Aug 28 '21 at 08:12
  • @JoséA.Zapata: I use v`-form` to binding data. https://github.com/cretueusebiu/vform – Cheer Up Aug 28 '21 at 08:13
  • @CheerUp Just provide the full code of your component. ` – StevenSiebert Aug 28 '21 at 08:18
  • @Fabalance: That's nothing to do with ` – Cheer Up Aug 28 '21 at 08:36
  • 2
    @CheerUp The point of providing the rest of the code is to have a reproducible example to test. If you don't give that, it's harder to pinpoint the exact issue. And word of advice: check the attitude, you won't get much help if you act like that. – José A. Zapata Aug 28 '21 at 08:40
  • The reason I dont include the common code like ` – Cheer Up Aug 28 '21 at 08:46
  • I think you need to assign form again, by creating a new Form and using the new variants array. – Keerthi Kumar P Aug 28 '21 at 09:56
  • @CheerUp As José stated, we need it to have a reproducible example. It doesn´t matter, if we know, where these tags belong. We need to know, if you done it right. Just try to reproduce your code, it will not work. You provided an empty array and have unclosed `html`. – StevenSiebert Aug 28 '21 at 10:53
  • @Fabalance: If you need more clear, kindly refer to this tutorial https://www.youtube.com/watch?v=Efr7SUrBUQw Thanks! – Cheer Up Aug 28 '21 at 11:59
  • 1
    @Fabalance: Do you mean I should write it in jsfiddle? – Cheer Up Aug 28 '21 at 12:05
  • @CheerUp You have a similar option for a snippet on SO. If you want to do it in JSFiddle, you can. Just add the link afterwards and I will take a look at it. – StevenSiebert Aug 28 '21 at 13:10
  • The problem has been solved – Cheer Up Aug 28 '21 at 13:14

1 Answers1

0

When rendering list using v-for do not use index variable from v-for as :key, especially not when loop content contains any <input> element and/or you are adding/removing/sorting items...

See the docs - Maintaining State

Note that the docs does not mention or discourage using index variable as :key in any way. But if you think about it, using index is indeed same as not using :key at all. Because role of :key is to establish relationship (identity) between each item used in the loop and the DOM that is generated for it. This is something index can't do...

key should be stable (not change over time) and unique over all the items in the list. Sometime the data already contain such item (for example when the data comes from server/database). If there is no data property with above mentioned features (as in your case where both variant_type and variant_options are editable by the user), just generate your own artificial key. There are multiple ways to generate unique id in JS

Example using "running index":

data() {
    return {
        nextId: 1,
        form: new Form({
            variants: [
                {
                    id: 0,
                    variant_type: '',
                    variant_options: '',
                },
            ],
        }),
    };
},
methods: {
    addVariant() {
        if (this.form.variants.length <= 1) {
            this.form.variants.push({
                id: this.nextId++,
                variant_type: '',
                variant_options: '',
            });
        } else {
            this.error = 'You can only add 2 type of varians';
            $('#errMsg').show();
        }
    },
}

...and use :key="variant.id" in the template

tony19
  • 125,647
  • 18
  • 229
  • 307
Michal Levý
  • 33,064
  • 4
  • 68
  • 86
  • So, what is the solution? Could you please solve this problem with code? I've stuck on this problem many days. – Cheer Up Aug 28 '21 at 12:03
  • Yo man, it's working. Thank you very much. You've made my day lighter. Still trying to understand how it's work. – Cheer Up Aug 28 '21 at 12:36