Search code examples
javascriptlaravelvuejs2laravel-bladevee-validate

Vee validate v3 ValidationObserver not working with dynamic validation provider added using v-for


I am using Vee Validate v3 for validating dynamic input generated using V-FOR, which is added or removed input elements based on user actions.

My issue was only the last input gets validated other inputs not getting validated. In the documentation, they had mentioned this issue while using V-IF & V-FOR documentation link

They told to use VueJS keep-alive component. but not working with V-FOR.

<validation-observer ref="observer" v-slot="{ handleSubmit }">
<form method="POST" action="{{ route('app.store') }}" @submit.prevent="handleSubmit(onSubmit)" class="form" enctype="multipart/form-data">
    <table class="table">
        <thead>
            <tr>
                <th>SI No</th>
                <th>input 1</th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="(item, index) in items" :key="item.id">
                <td>@{{ index + 1 }}</td>
                <td>
                    <keep-alive>
                        <validation-provider rules="required" v-slot="{ errors }" name="attribute">
                            <div class="form-group">
                                <input :name="'attribute' + item.id" class="form-control" v-model="item.attribute">
                                <span class="error" role="alert">

                                    @{{ errors[0] }}

                                </span>
                            </div>
                        </validation-provider>
                    </keep-alive>
                </td>
                <td>
                    <button type="button" class="btn btn-md btn-danger mt-4" @click="remove(index)">
                        <span class="ion-trash-a"></span>
                    </button>
                </td>
            </tr>
        </tbody>
    </table>


    <x-form-submit>Save</x-form-submit>

</form>

My js code

<script type="application/javascript">
        Vue.component('dynamic-form-wrapper', {
            template: '#dynamic-form-template',
            data() {
                return {
                    items: [
                        {
                            id: 1,
                            attribute: null,
                        },
                        {
                            id: 2,
                            attribute: null,
                        }
                    ],
                    id: 3
                }
            },
            methods: {
                async onSubmit() {
                    const valid = await this.$refs.observer.validate();
                    if (valid) {
                        document.getElementById("category-form").submit();
                        
                    }
                },
                add() {
                    this.items.push({
                        id: this.id,
                        attribute: null,
                    });
                    this.id ++;
                },
                remove(index) {
                    if (this.items.length != 1) {
                        this.items.splice(index, 1);
                    }
                }
            }
        })
    </script>

Thanks in advance


Solution

  • Each ValdationProvider needs a unique id. set :vid for each validation providers

    <keep-alive>
        <validation-provider :vid="'attribute' + item.id" rules="required" 
            v-slot="{ errors }" name="attribute">
            <x-v-form-input type="text" v-model="item.attribute" field="attribute">
            </x-v-form-input>
        </validation-provider>
    </keep-alive>
    

    Refer API docs for vid here: https://vee-validate.logaretm.com/v3/api/validation-provider.html#props