This project still active, feel free to clone, open issues or ask for help
Form Object is a simple layer on top of axios, it understands the Laravel validation error responses and handles it for you, now you can focus on the feedback you want to give to the users.
NOTE: version >=1.4.3+ requires Vue >=1.0
# Using the legendary NPM
npm install form-object --save
# Or using Yarn
yarn add form-object
<template>
<form @submit.prevent="submit">
<!-- Display a global message if there is any errors -->
<div class="alert alert-danger" v-if="form.errors.any()" v-cloak>
Please check the form and try again!
</div>
<!-- Apply custom classes when a field has an error -->
<div :class="{ 'has-error': form.errors.has('name') }">
<!-- No need to attach your component data to the form object -->
<input type="text" v-model="user.name">
<!-- Display the error message for a specific field -->
<div class="error" v-show="form.errors.has('name')" v-text="form.errors.get('name')"></div>
<!-- Or display all error messages for specific field -->
<div v-for="(error, key) in form.errors.getAll('name')" :key="key" v-text="error"></div>
<!-- Pass an instance of File to your model to support file uploads -->
<input type="file" @change="user.photo = $event.target.files[0]" accept="image/jpeg">
<!-- Disable buttons using form.isPending -->
<button type="submit" :disabled="form.isPending">Submit</button>
<!-- Get upload progress percentage using form.progress -->
<div class="progress-bar">
<div :style="{width: form.progress + '%'}"></div>
</div>
</div>
</form>
</template>
<script>
import Form from 'form-object';
export default {
data() {
return {
user: {name: 'Sahib', photo: null},
form: new Form()
}
},
methods: {
submit() {
this.form.submit('post', '/users', this.user).then(data => {
// This is the data returned from your server.
console.log(data);
}).catch(error => {
// Handle request errors.
});
}
}
}
</script>
You can get rid of all error messages calling the clear
method that belongs to the Errors
object, like this:
this.form.errors.clear();
Take note that all messages are removed automatically before sending the request, and in case you need to clear
an specific error message just pass the field's name to the clear
method, like this:
this.form.errors.clear('email');
In this way only that one will be removed from the error messages list.
Write this.form.submit('POST', ...)
can be too verbose for you, if it is the case you can use the
shortcut methods:
Send data
via POST request to the given url
, same as form.submit('POST', url, data)
.
Send data
via PATCH request to the given url
, same as form.submit('PATCH', url, data)
.
Send data
via PUT request to the given url
, same as form.submit('PUT', url, data)
.
Send data
via DELETE request to the given url
, same as form.submit('DELETE', url, data)
.
This method will send resource
via POST or PATCH request to the given url
, depending on whether
the resource has a property called id
, for example:
const resource = {name: 'John Doe'};
// This call...
form.save('/users', resource);
// Is the same as this call.
form.submit('POST', '/users', resource);
And if the resource
has an id
property:
const resource = {id: 123, name: 'John Doe'};
// Now that resource has an "id" property, this call...
form.save('/users', resource);
// Is the same as this call.
form.submit('PATCH', '/users/123', resource);
As you can see, the save
method will append the id
to the original url
automatically.
Use normal arrays when array inputs are needed, here is a simple example:
<template>
<div>
<div v-for="(color, i) in product.colors">
<input type="text" v-model="product.colors[i]" />
<div v-show="form.errors.has(`colors.${i}`)" v-text="form.errors.get(`colors.${i}`)"></div>
</div>
<div v-for="(photo, i) in product.photos">
<input type="file" @change="product.photos[i] = $event.target.files[0]" accept="image/jpeg" />
<div v-show="form.errors.has(`photos.${i}`)" v-text="form.errors.get(`photos.${i}`)"></div>
</div>
</div>
</template>
<script>
import Form from 'form-object';
export default {
data() {
return {
form: new Form(),
// Fill array as you need, I use null to simplify this example.
product: {
colors: [null, null],
photos: [null, null]
}
};
},
methods: {
async submit() {
await this.form.post('/arrays-support', this.product);
}
}
}
</script>
And your Laravel validation rules will be something like this:
$rules = [
'colors.*' => 'required',
'photos.*' => 'required|file',
];
Seems like Laravel pass the validation rules for required files if the array contains at least one element. If you find a workaround for this let me know!
You can customize the behaviour by modifying the Form.defaults
property.
In some cases, you will need to use a customized axios instance instead of the one that comes along with this package, to do this you can attach your own axios instance to the object defaults:
import axios from 'axios';
import Form from 'form-object';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
Form.defaults.axios = axios;
Please read the Axios documentation at https://github.com/mzabriskie/axios#promises