Last active
April 4, 2020 07:02
-
-
Save psychonetic/9b01d2b1eb04b9654d8c2627a2b1bcb5 to your computer and use it in GitHub Desktop.
Vue-Dropzone and Vee-Validate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Custom Validator to add errors into vuex store and also handle laravel form errors. | |
import { mapGetters } from 'vuex'; | |
import { CLEAR_FORM_ERRORS, ERROR } from '../vuex/types'; | |
import Vue from 'vue'; | |
export default { | |
data() { | |
return { | |
errors: [], | |
keepServerErrors: ['unique', 'boolean', 'exists', 'regular_chars', 'identifier', 'date'], | |
}; | |
}, | |
mounted() { | |
Object.keys(this.fields).map((field) => { | |
Vue.set(this.errors, field, undefined); | |
}); | |
}, | |
computed: { | |
...mapGetters([ | |
'formErrors', | |
]), | |
}, | |
methods: { | |
hasServerFormErrors() { | |
if (this.formErrors.length === 0) { | |
return false; | |
} | |
return true; | |
}, | |
resetFormErrors() { | |
this.$store.dispatch(CLEAR_FORM_ERRORS).then(() => { | |
this.errors = []; | |
this.$validator.errors.clear(); | |
}); | |
}, | |
addServerErrors() { | |
if (this.formErrors.hasOwnProperty(0)) { | |
this.formErrors[0].map((failed) => { | |
const field = failed.field; | |
if (this.fields.hasOwnProperty(field)) { | |
if (this.keepServerErrors.indexOf(failed.rule) != -1) { | |
this.errors[field] = failed.msg; | |
this.fields[field].valid = false; | |
this.fields[field].invalid = true; | |
} | |
} | |
}); | |
} | |
}, | |
collectErr(key) { | |
if (this.errors[key] !== undefined) { | |
return this.errors[key]; | |
} | |
return undefined; | |
}, | |
hasAnyError(arr) { | |
for (const index in arr) { | |
if (this.errors[arr[index]] !== undefined) { | |
return true; | |
} | |
} | |
return false; | |
}, | |
errorCount() { | |
return Object.keys(this.errors).length; | |
}, | |
hasError(key) { | |
if (this.errors[key] !== undefined) { | |
return true; | |
} | |
return false; | |
}, | |
delNullValues(object, keys) { | |
for (const property in object) { | |
if (object.hasOwnProperty(property) && keys.indexOf(property) !== -1) { | |
if (object[property] === null || object[property] === '') { | |
object[property] = undefined; | |
} | |
} | |
} | |
return object; | |
}, | |
}, | |
watch: { | |
veeErrors: { | |
handler(val, oldVal) { | |
this.errors = []; | |
val.items.map((err) => { | |
if (this.fields.hasOwnProperty(err.field) !== -1) { | |
this.errors[err.field] = err.msg; | |
} | |
}); | |
this.addServerErrors(); | |
}, | |
deep: true, | |
}, | |
formErrors: { | |
handler() { | |
this.errors = []; | |
this.addServerErrors(); | |
}, | |
}, | |
}, | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Laravel Custom FormRequest. | |
<?php | |
namespace App\Http\Requests; | |
use Illuminate\Foundation\Http\FormRequest; | |
class CoreFormRequest extends FormRequest { | |
protected $failed = []; | |
/** | |
* Add a field with detailed information about failed fields. | |
* @param \Illuminate\Contracts\Validation\Validator | |
*/ | |
public function withValidator($validator) | |
{ | |
$validator->after(function ($validator) { | |
$errors = $validator->errors()->getMessages(); | |
$obj = $validator->failed(); | |
foreach($obj as $input => $rules) { | |
$i = 0; | |
$fail = []; | |
foreach($rules as $rule => $ruleInfo){ | |
$key = $rule; | |
$fieldParts = explode(".", $input); | |
$clientInput = $fieldParts[0]; | |
if(count($fieldParts) > 1) { | |
$clientInput = $fieldParts[0].'['.$fieldParts[1].']'; | |
} | |
$fail = [ | |
'rule' => strtolower($rule), | |
'field' => $clientInput, | |
'msg' => $errors[$input][$i] | |
]; | |
$i++; | |
} | |
$this->failed[] = $fail; | |
} | |
if(count($this->failed) > 0) { | |
$validator->errors()->add('details', $this->failed); | |
} | |
}); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<v-uploader | |
:url="uploadUrl" | |
:mimes="uploader.mimes" | |
:remove-url="removeUrl" | |
v-model="form.mandat" | |
v-validate="'required'" | |
data-vv-name="mandat" | |
data-vv-as="SEPA-Mandat" | |
:has-error="hasError('mandat')" | |
:error="collectErr('mandat')" | |
label="SEPA-Mandat"> | |
</v-uploader> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="input--group"> | |
<label class="input--group--label">{{label}}</label> | |
<dropzone id="dropzone" | |
ref="dropzone" | |
:options="options" | |
:name="name" | |
@vdropzone-success="uploadDone" | |
@vdropzone-removed-file='remove' | |
:destroyDropzone="true"/> | |
<p class="input--group--error" v-if="hasError">{{ error }}</p> | |
</div> | |
</template> | |
<script> | |
import Dropzone from 'nuxt-dropzone' | |
import 'nuxt-dropzone/dropzone.css' | |
import axios from 'axios'; | |
import input from "../../mixins/input"; | |
export default { | |
props: { | |
label: { | |
type: String, | |
required: true, | |
}, | |
url: { | |
type: String, | |
required: true, | |
}, | |
removeUrl: { | |
type: String, | |
required: true, | |
}, | |
maxFiles: { | |
default: 1, | |
}, | |
mimes: { | |
default: null, | |
type: String, | |
}, | |
}, | |
name: 'VUploader', | |
mixins: [input], | |
components: { | |
Dropzone, | |
}, | |
created() { | |
this.options.url = this.url; | |
this.options.maxFiles = this.maxFiles; | |
this.options.acceptedFiles = this.mimes; | |
}, | |
data() { | |
return { | |
options: { | |
url: null, | |
maxFiles: 1, | |
maxFilesize: 5, | |
acceptedFiles: null, | |
addRemoveLinks: true, | |
headers: { | |
'Access-Control-Allow-Origin': '*', | |
}, | |
dictDefaultMessage: this.$t('dropzone.defaultMessage'), | |
dictFallbackMessage: this.$t('dropzone.fallbackMessage'), | |
dictFallbackText: this.$t('dropzone.fallbackText'), | |
dictFileTooBig: this.$t('dropzone.fileTooBig', { | |
filesize: '{filesize}', | |
maxFilesize: '{maxFilesize}' | |
}), | |
dictInvalidFileType: this.$t('dropzone.invalidFileType'), | |
dictResponseError: this.$t('dropzone.responseError', {statusCode: '{statusCode}'}), | |
dictCancelUpload: this.$t('dropzone.cancelUpload'), | |
dictCancelUploadConfirmation: this.$t('dropzone.cancelUploadConfirmation'), | |
dictRemoveFile: this.$t('dropzone.removeFile'), | |
dictMaxFilesExceeded: this.$t('dropzone.maxFilesExceeded'), | |
}, | |
uploaded: [], | |
}; | |
}, | |
methods: { | |
remove(file) { | |
this.uploaded.forEach((item) => { | |
if(item.file === file.upload.uuid) { | |
this.$emit('input', null) | |
axios.delete(`${this.removeUrl}?items=${item.id}`).then(() => { | |
console.debug('Deleted file.') | |
}).catch(() => { | |
console.error('Could not delete file.') | |
}) | |
} | |
}); | |
}, | |
uploadDone(file, response) { | |
this.uploaded.push( | |
{ | |
file: file.upload.uuid, | |
id: response.file.id | |
} | |
) | |
this.$emit('input', this.uploaded); | |
} | |
} | |
}; | |
</script> | |
<style lang="css" scoped> | |
.vue-dropzone { | |
width: 50%; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment