Joney Spark
Joney Spark

Reputation: 265

How to show Array of errors in Vue.js ? Backend Validation with Laravel

I have some complex data and I want to show the validation error array data in vue file but I can not do it because I have got some data that has an index and showing like contacts.0.name: ["...."].

Please share your opinion how I can show the error.

vue file

<template>
  <div>
    <form enctype="multipart/form-data" @submit.prevent="handleSubmit">
      <div v-for="(contact, index) in contacts" :key="index" class="row">
        <div class="col col-md-3">
          <div class="form-group mb-4">
            <label for="personName">Contact Person Name</label>
            <input
              id="personName"
              v-model="contact.name"
              type="text"
              class="form-control"
            />
            <small> Want to show here the error ? </small
            >
          </div>
        </div>

        <!-- Add or Remove button -->

        <div class="col col-md-12 text-right">
          <div class="row ml-4">
            <div v-show="index == contacts.length - 1">
              <button
                class="btn btn-warning mb-2 mr-2 btn-rounded"
                @click.prevent="add"
              >
                Add More
              </button>
            </div>
            <div v-show="index || (!index && contacts.length > 1)">
              <button
                class="btn btn-danger mb-2 mr-2 btn-rounded"
                @click.prevent="remove"
              >
                Remove
              </button>
            </div>
          </div>
        </div>
      </div>
    </form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      contacts: [
        {
          name: "",
        },
      ],

      errors: [],
    };
  },
  methods: {
    handleSubmit() {
      let data = new FormData();
      data.append("contacts", JSON.stringify(this.contacts));

      Request.POST_REQ(data, "/add-institute")
        .then(() => {
          alert("success");
        })
        .catch((err) => {
          this.errors = err.response.data.errors;
        });
    },
    add() {
      this.contacts.push({
        name: "",
        email: "",
        phone: "",
        alternate_phone: "",
      });
    },
    remove(index) {
      this.contacts.splice(index, 1);
    },
  },
};
</script>

controller file


public function add_institute(Request $request) {
  $request['contacts'] = json_decode($request['contacts'], true);
  $request->validate([
      'contacts.*.name'=> 'unique:institute_contact_people|distinct',
  ]);

  ...rest of code of insert 

  return response()->json("Success...");
}

Getting Error Response data

errors: {
  contacts.0.name: ["The contacts.0.name has already been taken.", "The contacts.0.name field has a duplicate value."]
  0: "The contacts.0.name has already been taken."
  contacts.1.name: ["The contacts.1.name has already been taken.", "The contacts.1.name field has a duplicate value."]
  0: "The contacts.1.name has already been taken."
}

Upvotes: 1

Views: 2141

Answers (2)

Niraj Gautam
Niraj Gautam

Reputation: 167

in your controller


 $request->validate([
        'ClinicName' => 'required|string|min:200',
        'Branches.*.BranchName'=>'required|string|min:200'
    ]);

in your vue3 file, to access the errors which will have keys such as, 'Branches.0.BranchName' then you can access the above error with for loop similar to this


<p v-if="form.errors['Branches.' + counter + '.BranchName']"
   class="mt-2 text-sm text-red-600 dark:text-red-500">
              {{ form.errors["Branches." + counter + ".BranchName"] }}
 </p>

here the counter can be any counter starting from 0.

Upvotes: 0

kissu
kissu

Reputation: 46706

Okay, so your error data is basically an object with array of errors in it. Pretty much like this

errors: {
  'contacts.0.name': [
    'The contacts.0.name has already been taken.',
    'The contacts.0.name field has a duplicate value.',
  ],
  'contacts.1.name': [
    'The contacts.1.name has already been taken.',
    'The contacts.1.name field has a duplicate value.',
  ],
},

For me, it will be better if you could achieve something like this as an error response (an array of objects with errors array in it)

betterErrors: [
  {
    location: 'contact.0.name',
    errors: [
      'The contacts.0.name has already been taken.',
      'The contacts.0.name field has a duplicate value.',
    ],
  },
  {
    location: 'contact.1.name',
    errors: [
      'The contacts.1.name has already been taken.',
      'The contacts.1.name field has a duplicate value.',
    ],
  },
],

For me, as of right now, it feels wrong but you can achieve a display of your errors with something like this

<template>
  <div>
    <div v-for="(error, key) in errors" :key="key">
      <hr />
      <span v-for="(errorItem, innerKey) in error" :key="innerKey" style="margin-top: 2rem">
        {{ errorItem }}
      </span>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      errors: {
        'contacts.0.name': [
          'The contacts.0.name has already been taken.',
          'The contacts.0.name field has a duplicate value.',
        ],
        'contacts.1.name': [
          'The contacts.1.name has already been taken.',
          'The contacts.1.name field has a duplicate value.',
        ],
      },
    }
  },
}
</script>

PS: having a :key with an array looping index is really bad tbh. That's why I do recommend a location field in your error response.

Upvotes: 1

Related Questions