question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to use vuelidate in input fields in a table ?

See original GitHub issue

Here I have a table where I am Showing data in tabular format and each column has input fields that can be edited. Then how can I check if a particular row is not empty or valid? I am using the bootstrap-vue table. Any help is highly appreciated.

Below is the code and its code pen is - https://codepen.io/kkdas202/pen/BaKjmZX?editors=1010

<b-table
        small
        :fields="fields"
        :items="ItemList"
        responsive="sm"
      >
        <template v-slot:cell(name)="data">
          <b-form-group>
            <b-input
              :id="`name-${data.index}`"
              placeholder="Enter name"
              v-model="data.item.name"
            ></b-input>
          </b-form-group>
        </template>
        <template v-slot:cell(email)="data">
          <b-form-group>
            <b-input
              :id="`email-${data.index}`"
              placeholder="Enter email"
              v-model="data.item.email"
            ></b-input>
          </b-form-group>
        </template>
</b-table>
Fields:
fields: [ {  key: 'name',  label: 'Name' },  {  key: 'email', label: 'Email' }],
items: [ { name:'John',  email: 'abc@gmail.com'}, { name: 'Jane', email: 'xyz@gmail.com' }]

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
LarryBarkercommented, Jun 4, 2021

@shentao Do you mean collection validation is going away? I have a similar use case, but a little more complicated. We’re using Vuex to load a list, and each row in the table is editable. I tried following the docs for collections, but am coming up short.

Here’s the code:

<template>
  <div v-if="currentProgram && localData" class="program">
    <h2>Program {{ $route.params.id }}</h2>
    <p>name: {{ currentProgram.program_name }}</p>
    <p>description: {{ currentProgram.description }}</p>
    <v-simple-table>
      <template v-slot:default>
        <thead>
          <tr>
            <th class="text-left" />
            <th class="text-left">Name</th>
            <th class="text-left">Description</th>
            <th class="text-left">Photo</th>
            <th class="text-left">Order</th>
            <th class="text-left">Deleted</th>
            <th class="text-left">Lessons</th>
          </tr>
        </thead>
        <tbody ref="table">
          <tr v-for="item in localData" :key="item.id">
            <td class="handle">::{{ item.id }}</td>
            <td>
              <v-text-field v-model="item.name" />
              <div v-if="!$v.localData.$each.name.required" class="error">The module name is required.</div>
            </td>
            <td>
              <v-text-field v-model="item.description" />
              <div v-if="!$v.localData.$each.name.required" class="error">The module description is required.</div>
            </td>
            <td>
              <v-img v-if="item.photo" :src="item.photo" width="50" />
              <v-select v-model="item.photo" :items="photos" />
              <div v-if="!$v.localData.$each.name.required" class="error">Please select a cover photo.</div>
            </td>
            <td>{{ item.order }}</td>
            <td>
              <v-checkbox v-model="item.deleted" :true-value="1" :false-value="0" />
            </td>
            <td>
              <v-btn icon :to="{ name: 'module', params: { module_id: item.id, program_id: $route.params.id } }">
                <v-icon>mdi-pencil-outline</v-icon>
              </v-btn>
            </td>
          </tr>
        </tbody>
      </template>
    </v-simple-table>
    <v-btn @click="addModule">Add Module</v-btn>
    <v-btn @click="saveModules">Save changes</v-btn>
  </div>
</template>

<script>
import { mapActions, mapGetters } from 'vuex';
import Sortable from 'sortablejs';
import { required } from 'vuelidate/lib/validators';

export default {
  data() {
    return {
      initialised: false,
      localData: [],
    };
  },
  computed: {
    ...mapGetters(['getProgram']),
    currentProgram() {
      return this.getProgram(this.$route.params.id);
    },
    activeModules() {
      return this.$store.state.adminPrograms.modules;
    },
    photos() {
      return this.$store.state.adminPrograms.modulePhotos;
    },
  },
  watch: {
    localData(value) {
      if (!value || this.initialised) return;

      this.initialised = true;
      this.$nextTick(function () {
        let table = this.$refs.table;
        const _self = this;
        Sortable.create(table, {
          onEnd({ newIndex, oldIndex }) {
            const rowSelected = _self.localData.splice(oldIndex, 1)[0];
            _self.localData.splice(newIndex, 0, rowSelected);
            _self.localData.forEach((element, index) => {
              element.order = index + 1;
            });
          },
          handle: '.handle',
        });
      });
    },
    activeModules(value) {
      if (this.initialised) {
        this.localData = value;
      }
    },
  },
  async beforeMount() {
    await this.getModules(this.$route.params.id);
    await this.getModulesPhotos();
    this.localData = [...this.$store.state.adminPrograms.modules];
  },

  methods: {
    ...mapActions(['getModules', 'getModulesPhotos', 'setModules']),
    addModule() {
      const newModule = {
        id: null,
        name: '',
        description: '',
        deleted: 0,
        order: this.localData.length + 1,
      };

      this.localData.push(newModule);
    },
    saveModules() {
      if (this.validate()) {
        setModules({ modules: localData, program_id: $route.params.id })
      }
    },
    validate() {
      this.$v.$touch();
      return this.$v.$valid;
    },
  },
  validations: {
    localData: {
      required,
      $each: {
        name: {
          required,
        },
        description: {
          required,
        },
        photo: {
          required,
        },
      },
    },
  },
};
</script>

<style scoped>
.handle {
  cursor: move;
  cursor: -webkit-grab;
}
</style>

I can get the validation to trigger, but the error messages show up on every row, not just the one failing validation. Any thoughts are appreciated 🙏

0reactions
shentaocommented, Jun 4, 2021

Nope. Working with Node.js mostly. Why the question?

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to use Vuelidate with editable Vuetify Data Table field
Render one dialog on the page and keep track of which row the user is editing in a data property. This property is...
Read more >
Vuelidate | A Vue.js model validation library
Simple, lightweight model-based validation for Vue.js.
Read more >
[Part 5] Validate Table Rows and Fields with Bootstrap Vue
Learn how to validate table rows and input fields with BootstrapVue and HTML form validation.
Read more >
Form Validation With Vuelidate in Vue.js
In this post, you'll use a third-party library named Vuelidate to perform model validation depending on a particular rule set.
Read more >
How to use Vuelidate with editable Vuetify Data Table field- ...
[Solved]-How to use Vuelidate with editable Vuetify Data Table field-Vue.js ... You don't want to render a dialog for each row in your...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found