Hello I am building one project. Where user can send up to 5 images and up to 10 songs with the text. But when I send request to the server, where I handle with Laravel, I can't get those files.
// my data object from VueJS
data() {
return {
formData: new FormData(),
pikir: {
body: '',
},
isLoading: false,
images: [],
songs: [],
}
}
// imagePreview method from VuejS
imagePreview(event) {
let input = event.target;
if (input.files[0]) {
if (input.files.length <= 5) {
for (let i = 0; i < input.files.length; i++) {
let reader = new FileReader();
reader.onload = e => {
this.images.push(e.target.result);
}
reader.readAsDataURL(input.files[i]);
}
Array.from(Array(event.target.files.length).keys())
.map(x => {
this.formData
.append('images',
event.target.files[x], event.target.files[x].name);
});
} else {
alert('You can upload up to 5 images');
}
}
}
// musicPreview method from VueJS
musicPreview(event) {
let input = event.target;
if (input.files.length <= 5) {
for (let i = 0; i < input.files.length; i++) {
this.songs.push(input.files[i].name.replace('.mp3', ''));
}
Array.from(Array(event.target.files.length).keys())
.map(x => {
this.formData
.append('songs',
event.target.files[x], event.target.files[x].name);
});
} else {
alert('You can upload up to 10 songs');
}
}
// sharePikir method from VueJS
sharePikir() {
this.formData.append('body', this.pikir.body);
axios.put('/api/pikirler', this.formData)
.then(response => {
this.pikir.body = '';
this.isLoading = false;
})
.catch(() => {
this.isLoading = false;
});
},
<form action="#" id="share-pikir">
<label for="pikir">
Näme paýlaşmak isleýärsiňiz? {{ pikirSymbolLimit }}
</label>
<input type="text" name="pikir" id="pikir" maxlength="255"
v-model="pikir.body"
#keyup="handleSymbolLimit()">
<div class="emoji">
<i class="fa fa-smile-o"></i>
</div>
<div class="photo-music left">
<label for="music-upload">
<i class="fa fa-music"></i>
</label>
<input type="file" name="songs[]" id="music-upload"
accept="audio/mp3"
#change="musicPreview($event)"
multiple>
<i class="divider"></i>
<label for="image-upload">
<i class="fa fa-image"></i>
</label>
<input type="file" name="images[]" id="image-upload"
#change="imagePreview($event)"
multiple>
</div>
<div class="share right">
<button
:class="{ 'btn-medium': true, 'is-loading': isLoading }"
#click.prevent="sharePikir($event)">
Paýlaşmak
</button>
</div>
</form>
I put my front end stuff above and in my Laravel side I just return all requests:
public function store(){
return request()->all();
}
And these are what I get from request:
I couldn't found what is wrong. Thank you in advance.
Oh yeah! you're missing this part. You need to define this.
axios.defaults.headers.post['Content-Type'] = 'multipart/form-data';
this my solutuion
export default {
data (){
return {
attachment : { name : null,file: null }
}
},
methods : {
onFileChange(event) {
this.attachment.file = event.target.files[0]
},
attachmentCreate() {
var form = new FormData();
form.append('name',this.attachment.name);
form.append('file',this.attachment.file);
this.$http.post('attachment',form).then(response=>{
console.log("oke")
})
},
}
}
<input type="file" class="form-control" #change="onFileChange">
Check this post, maybe your problem is solved:
[https://stackoverflow.com/questions/55895941/success-upload-file-via-postman-but-fail-on-front-end-vue/73698108#73698108][1]
Related
I have a problem capturing multiple images to my function in vue and pass to the controller. I am trying to modify my blade file which works well when using just the normal form. I am trying to modify to vue but I have a problem with image section. Please assist me on how to achieve this.
my form:
<label for="">Description</label>
<textarea name="description" class="form-control" v-model="description"> </textarea>
<label for="">Images</label>
<input type="file" #change="fieldChange" class="form-control input-sm" name="images[]"
multiple>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
The vue section
data(){
return {
id:'',
price:'',
title:'',
description:'',
location:'',
images:[],
}
},
methods:{
fieldChange(e){
let selectedFiles=e.target.files;
if(!selectedFiles.length){
return false;
}
for(let i=0;i<selectedFiles.length;i++){
this.images.push(selectedFiles[i]);// am able to console the images
}
},
saveImageData(){
var self=this;
axios.post('/senddata',{
title:this.title,
description:this.description,
location:this.location,
images:this.images.file.name,
price:this.price,
})
},
My Laravel function
public function store(Request $request)
{
$product=Products::create([
'title'=>$request['title'],
'description'=>$request['description'],
'price'=>$request['price'],
'location'=>$request['location']
]);
$images= $request->file('images');
foreach ($images as $image){
$move=$image->move(public_path().'/images2/',$image->getClientOriginalName());
if($move){
$imagedata=Images::create([
'title'=>$image->getClientOriginalName(),
'filename'=>$image->getClientOriginalName()
]);
$product->images()->attach([$imagedata->id]);
}
Here is the working code for vuejs part - https://picupload.netlify.app/
https://github.com/manojkmishra/dw_take5/blob/master/src/components/ImageUploader.vue
Vue part
<template>
<div class="uploader"
#dragenter="OnDragEnter"
#dragleave="OnDragLeave"
#dragover.prevent
#drop="onDrop"
:class="{ dragging: isDragging }">
<div class="upload-control" v-show="images.length">
<label for="file">Select files</label>
<button #click="upload">Upload</button>
</div>
<div v-show="!images.length">
<i class="fa fa-cloud-upload"></i>
<p>Drag your images here</p><div>OR</div>
<div class="file-input">
<label for="file">Select files</label>
<input type="file" id="file" #change="onInputChange" multiple>
</div>
</div>
<div class="images-preview" v-show="images.length">
<div class="img-wrapper" v-for="(image, index) in images" :key="index">
<img :src="image" :alt="`Image Uplaoder ${index}`">
<div class="details">
<span class="name" v-text="files[index].name"></span>
<span class="size" v-text="getFileSize(files[index].size)"> </span>
</div>
</div>
</div>
<div v-show="images.length" class="progress">
<div
class="progress-bar progress-bar-info progress-bar-striped"
role="progressbar" :aria-valuenow="progress"
aria-valuemin="0" aria-valuemax="100"
:style="{ width: progress + '%' }"
>
{{ progress}}%
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default
{ data: () => ({ isDragging: false, dragCount: 0, files: [],images: [] ,progress:0}),
methods: {
OnDragEnter(e) { e.preventDefault();
this.dragCount++;
this.isDragging = true;
return false;
},
OnDragLeave(e) { e.preventDefault();
this.dragCount--;
if (this.dragCount <= 0) this.isDragging = false;
},
onInputChange(e) { const files = e.target.files;
Array.from(files).forEach(file => this.addImage(file));
},
onDrop(e) {console.log('ondrop-evnt e=',e)
e.preventDefault();
e.stopPropagation();
this.isDragging = false;
const files = e.dataTransfer.files;
Array.from(files).forEach(file => this.addImage(file));
},
addImage(file) {console.log('addimage file=',file)
if (!file.type.match('image.*')) { this.$toastr.e(`${file.name} is not an image`);
return;
}
this.files.push(file);
const img = new Image(),
reader = new FileReader();
reader.onload = (e) => this.images.push(e.target.result);
reader.readAsDataURL(file);
console.log('addimage this.images=',this.images)
},
getFileSize(size) { const fSExt = ['Bytes', 'KB', 'MB', 'GB'];
let i = 0;
while(size > 900) { size /= 1024; i++; }
return `${(Math.round(size * 100) / 100)} ${fSExt[i]}`;
},
upload() { //this.progress = '0';
const formData = new FormData();
this.files.forEach(file =>
{ formData.append('images[]', file, file.name); });
console.log('upload triggered FormData=',formData)
// resp=axios.post('http://127.0.0.1:8000/sendemail1',this.formData);
// axios.post('http://127.0.0.1:8000/api/imagesupload', formData,
axios.post('https://uat.oms.dowell.com.au/api/imagesupload', formData,
{onUploadProgress:uploadEvent=>{ this.progress=Math.round(uploadEvent.loaded/uploadEvent.total*100);
console.log('upld prges:'+ Math.round(uploadEvent.loaded/uploadEvent.total*100)+'%')
}
})
//axios.post('https://uat.oms.dowell.com.au/api/imagesupload', formData)
.then(response => {
this.$toastr.s('All images uplaoded successfully');
this.images = [];
this.files = [];
this.progress = 0;
})
.catch(() => {
this.$toastr.e('Could not upload the files!');
this.images = [];
this.files = [];
this.progress = 0;
});
}
}
}
</script>
Another version with vuetify
https://github.com/manojkmishra/take5-front-admin/blob/master/src/components/img/imgup.vue
Here is laravel part
public function imagesupload(Request $request){
if (count($request->images)) {
foreach ($request->images as $image) {
$image->store('images');
}
}
return response()->json(["message" => "Done"]);
}
Another way in laravel is here
https://github.com/manojkmishra/take5-api/blob/master/app/Http/Controllers/PicController.php
I have tried to upload a file using vue.js as front end technology and laravel in the back end. I have tried to pass the file object using formData javascript object but the server responds as the value is not passed.
I have tried to log the file using console.log and it appropriately displays the data.
Consider that I have discarded some field names.
Template Code
<template>
<b-container>
<div align="center">
<b-card class="mt-4 mb-4 col-md-8" align="left" style="padding: 0 0;">
<card-header slot="header" />
<b-form>
<div class="row">
<div class="col-6 col-md-6">
<b-button
type="submit"
variant="success"
class="float-right col-md-5"
v-if="!update"
#click="save"
squared
>
<i class="fas fa-save"></i>
Save
</b-button>
</div>
</div>
<hr style="margin-top: 10px;" />
<b-form-group
label-cols="12"
label-cols-lg="3"
label-for="input-2"
label="Remark: "
label-align-sm="right"
label-align="left"
>
<b-form-textarea
id="textarea"
v-model="record.remark"
rows="2"
max-rows="3"
></b-form-textarea>
</b-form-group>
<b-form-group
label-cols="12"
label-cols-lg="3"
label-for="input-2"
label="Remark: "
label-align-sm="right"
label-align="left"
>
<b-form-file
v-model="record.attachement"
:state="Boolean(record.attachement)"
placeholder="Choose a file..."
drop-placeholder="Drop file here..."
></b-form-file>
</b-form-group>
</b-form>
<status-message ref="alert" />
</b-card>
</div>
</b-container>
</template>
Script Code
<script>
import { mapGetters, mapActions } from "vuex";
export default {
props: ["id", "user_id"],
data: () => ({
record: {
remark: "",
attachement: null
}
}),
methods: {
...mapActions([
"addBenefitRequest",
]),
save(evt) {
evt.preventDefault();
this.$validator.validate().then(valid => {
if (valid) {
const Attachement = new FormData();
Attachement.append("file", this.record.attachement);
var object = {
remark: this.remark
};
this.addBenefitRequest(object, Attachement);
}
});
},
},
computed: mapGetters([
"getStatusMessage",
"getBenefitRequest",
])
};
</script>
Store Code
async addBenefitRequest({ commit }, object, Attachement) {
try {
const response = await axios.post(
commonAPI.BENEFIT_BASE_URL + "/benefit-requests",
object,
Attachement,
{
headers: {
"Content-Type": "multipart/form-data"
}
}
);
commit("pushBenefitRequest", response.data);
commit("setStatusMessage", "Record has been added.");
} catch (error) {
return error
},
Controller Code
public function store(Request $request, Request $request2)
{
$this->validate($request, [
'employee_id' => 'required|string',
'requested_date' => 'required|date',
// 'benefit_type_id' => 'required|string|exists:benefit_types,id',
'reason' => 'required|string',
]);
$this->validate($request2, [
'attachement' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048'
]);
// $success = BenefitRequest::exists($request->employee_id);
// if(!$success)
// return response()->json("Employee doesn't exist", 422);
$id = (string) Str::uuid();
if($request2->attachement)
{
$attachement = $request2->file('attachement')->store('Benefits');
$request->merge(['attachement' => $attachement]);
}
// $request->attachement = $request->file('attachement')->store('Benefits');
$request->merge(['id' => $id]);
BenefitRequest::create($request->all());
return response()->json('Saved', 201);
}
Route
$router->post('',
['uses' => 'BenefitRequestController#store',
'group'=>'Benefit requests',
'parameter'=>'employee_id, requested_date, requested_by, benefit_type_id, reason, remark, status',
'response'=>'<statusCode, statusMessage>'
]);
Here is an example. you can try it
index.vue
`<div id="app">
<div v-if="!image">
<h2>Select an image</h2>
<input type="file" #change="onFileChange">
</div>
<div v-else>
<img :src="image" />
<button #click="removeImage">Remove image</button>
</div>
</div>`
new Vue({
el: '#app',
data: {
image: ''
},
methods: {
onFileChange(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
},
createImage(file) {
var image = new Image();
var reader = new FileReader();
var vm = this;
reader.onload = (e) => {
vm.image = e.target.result;
};
reader.readAsDataURL(file);
},
removeImage: function (e) {
this.image = '';
}
}
})
I write codes with Vuex to login and logout in my Laravel single page application it's working well but when i login to an account the profiles information (name, address, Email, ...)doesn't show in profile but after i reload the page the profile information loads, and when another user try the profile the data of the last person that login shown to him/her
auth.js:
export function registerUser(credentials){
return new Promise((res,rej)=>{
axios.post('./api/auth/register', credentials)
.then(response => {
res(response.data);
})
.catch(err => {
rej('Somthing is wrong!!')
})
})
}
export function login(credentials){
return new Promise((res,rej)=>{
axios.post('./api/auth/login', credentials)
.then(response => {
res(response.data);
})
.catch(err => {
rej('The Email or password is incorrect!')
})
})
}
export function getLoggedinUser(){
const userStr = localStorage.getItem('user');
if(!userStr){
return null
}
return JSON.parse(userStr);
}
store.js:
import {getLoggedinUser} from './partials/auth';
const user = getLoggedinUser();
export default {
state: {
currentUser: user,
isLoggedIn: !!user,
loading: false,
auth_error: null,
reg_error:null,
registeredUser: null,
},
getters: {
isLoading(state){
return state.loading;
},
isLoggedin(state){
return state.isLoggedin;
},
currentUser(state){
return state.currentUser;
},
authError(state){
return state.auth_error;
},
regError(state){
return state.reg_error;
},
registeredUser(state){
return state.registeredUser;
},
},
mutations: {
login(state){
state.loading = true;
state.auth_error = null;
},
loginSuccess(state, payload){
state.auth_error = null;
state.isLoggedin = true;
state.loading = false;
state.currentUser = Object.assign({}, payload.user, {token: payload.access_token});
localStorage.setItem("user", JSON.stringify(state.currentUser));
},
loginFailed(state, payload){
state.loading = false;
state.auth_error = payload.error;
},
logout(state){
localStorage.removeItem("user");
state.isLoggedin = false;
state.currentUser = null;
},
registerSuccess(state, payload){
state.reg_error = null;
state.registeredUser = payload.user;
},
registerFailed(state, payload){
state.reg_error = payload.error;
},
},
actions: {
login(context){
context.commit("login");
},
}
};
general.js:
export function initialize(store, router) {
router.beforeEach((to, from, next) => {
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
const currentUser = store.state.currentUser;
if(requiresAuth && !currentUser) {
next('/login');
} else if(to.path == '/login' && currentUser) {
next('/');
} else {
next();
}
if(to.path == '/register' && currentUser) {
next('/');
}
});
axios.interceptors.response.use(null, (error) => {
if (error.resposne.status == 401) {
store.commit('logout');
router.push('/login');
}
return Promise.reject(error);
});
if (store.getters.currentUser) {
setAuthorization(store.getters.currentUser.token);
}
}
export function setAuthorization(token) {
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`
}
I think that this issue is relate to my localstorage, how can i fix this?
I'm novice at the Vue and don't have any idea what is the problem.
Login Component:
<template>
<main>
<form #submit.prevent="authenticate">
<div class="grid-x grid-padding-x">
<div class="small-10 small-offset-2 cell" v-if="registeredUser">
<p class="alert success">Welcome {{registeredUser.name}}</p>
</div>
<div class="small-10 small-offset-2 cell" v-if="authError">
<p class="alert error">
{{authError}}
</p>
</div>
<div class="small-2 cell">
<label for="email" class="text-right middle">Email:</label>
</div>
<div class="small-10 cell">
<input type="email" v-model="formLogin.email" placeholder="Email address">
</div>
<div class="small-2 cell">
<label for="password" class="text-right middle">Password:</label>
</div>
<div class="small-10 cell">
<input type="password" v-model="formLogin.password" placeholder="Enter password">
</div>
<div class="small-10 small-offset-2 cell">
<div class="gap"></div>
<input type="submit" value="Login" class="button success expanded">
</div>
</div>
</form>
</main>
</template>
<script>
import {login} from '../../partials/auth';
export default {
data(){
return {
formLogin: {
email: '',
password: ''
},
error: null
}
},
methods:{
authenticate(){
this.$store.dispatch('login');
login(this.$data.formLogin)
.then(res => {
this.$store.commit("loginSuccess", res);
this.$router.push({path: '/profile'});
})
.catch(error => {
this.$store.commit("loginFailed", {error});
})
}
},
computed:{
authError(){
return this.$store.getters.authError
},
registeredUser(){
return this.$store.getters.registeredUser
}
}
}
</script>
Localstorage data is once loaded on page load, so when you use setItem, this won't be visible until the next time.
You should store the data to vuex store, and use that as the source. Only set and get the data from localstorage on page loads.
Otherwise use something like: https://github.com/robinvdvleuten/vuex-persistedstate
I solved the problem.I have this code in my EditProfile component.
methods: {
getAuthUser () {
axios.get(`./api/auth/me`)
.then(response => {
this.user = response.data
})
},
}
this.user = response.data is wrong, I changed to this:
getAuthUser () {
this.user = this.$store.getters.currentUser
},
I am making a simple website that has a feature to upload images. I tried it Laravel way which I made it in blade template and it works fine. Now I am trying to make it inside Vue Components
Here's my Create.vue
<template>
<div>
<div class="row">
<input type="hidden" name="_token" :value="csrf">
<div class="col-md-5">
<div class="detail-container">
<label for="title">Book Title:</label>
<input type="text" name="title" id="title" v-model="book_title" class="form-control">
</div>
<div class="detail-container">
<label for="title">Book Description:</label>
<textarea type="text" name="description" id="description" v-model="book_description" class="form-control" rows="5"></textarea>
</div>
<div class="detail-container">
<label for="title">Tags:</label>
<multiselect v-model="tags" :show-labels="false" name="selected_tags" :hide-selected="true" tag-placeholder="Add this as new tag" placeholder="Search or add a tag" label="name" track-by="id" :options="tagsObject" :multiple="true" :taggable="true" #tag="addTag" #input="selectTags">
<template slot="selection" slot-scope="tags"></template>
</multiselect>
</div>
</div>
<div class="col-md-7">
<!-- BOOK COVER WILL GO HERE -->
<div class="detail-container">
<label>Book Cover:</label>
<input type="file" class="form-control-file" id="book_cover" name="selected_cover" #change="onFileChange">
<small id="fileHelp" class="form-text text-muted">After you select your desired cover, it will show the preview of the photo below.</small>
<div id="preview">
<img v-if="url" :src="url" height="281" width="180" />
</div>
</div>
</div>
<div class="detail-container" style="margin-top: 20px;">
<button class="btn btn-primary" #click="saveBook()">Next</button>
</div>
</div>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
// register globally
Vue.component('multiselect', Multiselect)
export default {
// OR register locally
components: { Multiselect },
data () {
return {
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
url: null,
selected_cover: null,
tags: [],
tagsObject: [],
selected_tags: [],
book_title: '',
book_description: ''
}
},
methods: {
getTags() {
let vm = this;
axios.get('/admin/getTags').then(function(result){
let data = result.data;
for(let i in data) {
vm.tagsObject.push({id: data[i].id, name: data[i].name});
}
});
},
addTag (newTag) {
const tag = {
name: newTag,
id: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.tagsObject.push(tag);
this.tags.push(tag);
},
selectTags(value) {
this.selected_tags = value.map(a=>a.id);
},
onFileChange(e) {
const file = e.target.files[0];
this.url = URL.createObjectURL(file);
this.selected_cover = file;
},
saveBook() {
const fd = new FormData();
fd.append('image', this.selected_cover, this.selected_cover.name)
console.log(this.selected_cover);
var book_details = {
'title': this.book_title,
'description': this.book_description,
'book_cover': this.selected_cover,
'tags': this.selected_tags
};
axios.post('/admin/saveBook', book_details).then(function(result){
console.log('done')
})
}
},
created() {
this.getTags();
}
}
</script>
<!-- New step!
Add Multiselect CSS. Can be added as a static asset or inside a component. -->
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
and here's my controller
public function store(Request $request)
{
$this->validate(request(), [
'title' => 'required|min:5',
'description' => 'required|min:10',
'book_cover' => 'required|image|mimes:jpeg,jpg,png|max:10000'
]);
// File Upload
if($request->hasFile('book_cover')) {
$fileNameWithExt = $request->file('book_cover')->getClientOriginalName();
// GET FILE NAME
$filename = pathinfo($fileNameWithExt, PATHINFO_FILENAME);
// GET EXTENSION
$extension = $request->file('book_cover')->getClientOriginalExtension();
// File Unique Name
$fileNameToStore = $filename. '_'. time().'.'.$extension;
$path = $request->file('book_cover')->storeAs('public/book_covers', $fileNameToStore);
} else {
$fileNameToStore = 'noimage.jpg';
}
$book = new Book;
$book->title = request('title');
$book->description = request('description');
$book->book_cover = $fileNameToStore;
$book->save();
$book->tags()->sync($request->tags, false);
return back()->with('success', 'Book Created Successfully!');
}
I never touched my controller because this is what I used when I do this feature in Laravel Way but when I save it, the details are being saved but the image is not uploading instead it saves noimage.jpg in the database. Does anyone know what I am doing wrong?
i tried to add this part const fd = new FormData(); in book_details but when i console.log(fd) it returned no data.
you should pass the fd object and not the book_details in your POST request.
you could do it something like this.
onFileChange(e) {
const file = e.target.files[0];
// this.url = URL.createObjectURL(file);
this.selected_cover = file;
},
saveBook() {
const fd = new FormData();
fd.append('image', this.selected_cover)
fd.append('title', this.book_title)
fd.append('description', this.book_description)
fd.append('book_cover', URL.createObjectURL(this.selected_cover))
fd.append('tags', this.selected_tags)
axios.post('/admin/saveBook', fd).then(function(result){
console.log('done')
})
}
and also, you can't just console.log the fd in the console. what you can do instead is something like this
for (var pair of fd.entries()) {
console.log(pair[0]+ ', ' + pair[1]);
}
FormData is a special type of object which is not stringifyable and cannot just be printed out using console.log. (link)
I am developing an application with with Laravel 5.3 and Vue 2 I implemented a form-validation via Vue 2 but the it doesn't check the request for any errors on client-side it firstly lets every single request to be sent to the server and then displays the errors which are sent back from the server, in the following you can find my code
class Form {
constructor(data) {
this.originalData = data;
for (let field in data) {
this[field] = data[field];
}
this.errors = new Errors();
}
data() {
let data = {};
for (let property in this.originalData) {
data[property] = this[property];
}
return data;
}
reset() {
for (let field in this.originalData) {
this[field] = '';
}
this.errors.clear();
}
post(url) {
return this.submit('post', url);
}
submit(requestType, url) {
return new Promise((resolve, reject) => {
axios[requestType](url, this.data())
.then(response => {
this.onSuccess(response.data);
resolve(response.data);
})
.catch(error => {
this.onFail(error.response.data);
reject(error.response.data);
});
});
}
onSuccess(data) {
alert(data.message);
this.reset();
}
onFail(errors) {
this.errors.record(errors);
}
}
and this is the `Vue class
` `new Vue({
el: "#form",
data: {
form: new Form({
name: '',
description: ''
})
},
methods: {
onSubmit() {
this.form.post('/admin/category');
//.then(response => alert('Item created successfully.'));
//.catch(errors => console.log(errors));
},
onSuccess(response) {
alert(response.data.message);
form.reset();
}
}
});`
and this is my HTML form
<form method="post" id="form" action="{{ url('admin/category') }}" '
#submit.prevent="onSubmit" #keydown="form.errors.clear($event.target.name)">
{{ csrf_field() }}
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" name="name"
v-model="form.name" placeholder="Name">
<span class="help is-danger"
v-if="form.errors.has('name')" v-text="form.errors.get('name')"></span>
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea class="form-control" id="description" name="description"
v-model="form.description" placeholder="Description"></textarea>
<span class="help is-danger"
v-if="form.errors.has('description')"
v-text="form.errors.get('description')"></span>
</div>
<button type="submit" class="btn btn-default" :disabled="form.errors.any()">Create New Category</button>
</form>
Question:
I need to modify the code in a way that firstly it checks on client side and if it finds any errors prevent the request from being sent to the server not letting every single request to be sent to server and then displays the errors sent back from the server
You can use any type of client side validation with your setup, just before you submit the form you can take the data from the Form class and validate it with vanilla javascript or any other validation library.
Let's use validate.js as an example:
in your onSubmit method you can do:
onSubmit() {
//get all the fields
let formData = this.form.data();
//setup the constraints for validate.js
var constraints = {
name: {
presence: true
},
description: {
presence: true
}
};
//validate the fields
validate(formData, constraints); //you can use this promise to catch errors
//then submit the form to the server
this.form.post('/admin/category');
//.then(response => alert('Item created successfully.'));
//.catch(errors => console.log(errors));
},