vue-dropzoneJs uploads 0 data to POST api endpoint but gives 200 oke - laravel

Simple form with the image upload and a title / description input
<template>
<div class="upload-form">
<form action="api/album" method="POST" enctype="multipart/form-data">
<div class="form-group">
<label for="title">Title</label>
<input
v-bind="form.title"
type="text"
class="form-control"
id="title"
required
/>
</div>
<div class="form-group">
<label for="description">description</label>
<input
v-bind="form.Description"
type="text"
class="form-control"
id="description"
required
/>
</div>
Upload a cover image here
<vue-dropzone
ref="dropzoneJs"
id="dropzone"
:options="options"
v-on:vdropzone-sending="sendingEvent"
></vue-dropzone>
<button
v-on:click="processQueue"
id="upload"
type="submit"
class="btn btn-primary"
>
Upload
</button>
</form>
</div>
</template>
<script>
import vueDropzone from "vue2-dropzone";
export default {
data() {
return {
options: {
url: "http://127.0.0.1:8000/api/album",
addRemoveLinks: true,
maxFiles: 1,
maxFilesize: 4,
autoProcessQueue: false,
dictDefaultMessage: '<i class="fas fa-cloud-upload-alt"></i>UPLOAD',
},
form: {
title: "",
Description: "",
},
};
},
components: {
vueDropzone: vueDropzone,
},
methods: {
processQueue() {
this.$refs.dropzoneJs.processQueue();
},
sendingEvent(file, xhr, formData) {
formData.append("title", this.form.title);
formData.append("description", this.form.Description);
},
},
};
</script>
<style scoped>
#upload {
margin-top: 5px;
}
.upload-form {
margin-top: 75px;
}
</style>
Form get's send to laravel backend controller via this route
Route::post('/album', [AlbumController::class, 'store'])->name('album.post');
Method inside of controller just dumps the request variable
public function store(Request $request)
{
dd($request);
}
The upload hits the POST endpoint and prints out the $request variable, but no title, description or image are inside.

After some trial and error I have found a solution
1: I removed the form tag
2: I used v-model instead of v-bind
3: changed the URL inside of my options object to api/album
these changes seem to have fixed my issue and dd($request) now prints the title / description and the file

Related

Vue.js/Laravel: pass category id to Vue.js component

I'm using Vue.js with Laravel and facing a problem. I want to pass category id from the blade file to the Vue.js component as a prop. But don't know what is good practice and the right way for this.
I've defined the route something like this:
Route::view('/categories/{category}/edit', 'edit')->name('categories.edit');
and my edit.blade.php file is:
#extends('master')
#section('vue')
<div id="app">
<categories-edit :id=""></categories-edit>
</div>
#endsection
The Vue.js component code is:
<template>
<div class="container py-5">
<div class="row">
<div class="col-lg-12">
<div class="mb-3">
<label for="name" class="form-label">Name:</label>
<input type="text" v-model="formState.name" name="name" class="form-control" id="name" placeholder="Category Name" autocomplete="off">
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'CategoriesEdit',
props: ['id'],
data: function () {
return {
formState: {
name: '',
photo: ''
}
}
},
mounted() {
},
methods: {
loadInitialData: function () {
const self = this;
axios.get(``).then(function (response) {
}).catch(function (err) {
});
}
}
}
</script>
When I'm entering the URL in the web browser. I'm getting this error.
http://example.test/categories/1/edit
Output:
Undefined variable $category
Since you are using Route::view() you do not have the traditional way of getting route parameters and pass them to the view. Luckily you can always get these on the request object and there is a request() helper that makes it easier for Blade views.
<categories-edit :id="{{ request()->route('category') }}"></categories-edit>

Toggle form in nested v-for loop in VueJS

I have a list of nested comments. Under each comment, I'd like to add a "reply" button that, when click, show a reply form.
For now, everytime I click a "reply" button, it shows the form. But the thing is, I'd like to show only one form on the whole page. So basically, when I click on "reply" it should close the other form alreay opened and open a new one under the right comment.
Edit :
So I was able to make some slight progress. Now I'm able to only have one active form opening on each level of depth in the nested loop. Obviously, what I'm trying to do now is to only have one at all.
What I did was emitting an event from the child component and handle everything in the parent component. The thing is, it would work great in a non-nested comment list but not so much in my case...
Here is the new code:
In the parentComponent, I have a handleSelected method as such:
handleSelected (id) {
if(this.selectedItem === id)
this.selectedItem = null;
else
this.selectedItem = id;
},
And my childComponent:
<template>
<div v-if="comment">
<div v-bind:style=" iAmSelected ? 'background: red;' : 'background: none;' ">
<p>{{ comment.author.name }}<br />{{ comment.created_at }}</p>
<p>{{ comment.content }}</p>
<button class="button" #click="toggle(comment.id)">Répondre</button>
<button class="button" #click="remove(comment.id)">Supprimer</button>
<div v-show="iAmSelected">
<form #submit.prevent="submit">
<div class="form-group">
<label for="comment">Votre réponse</label>
<textarea class="form-control" name="comment" id="comment" rows="5" v-model="fields.comment"></textarea>
<div v-if="errors && errors.comment" class="text-danger">{{ errors.comment[0] }}</div>
</div>
<button type="submit" class="btn btn-primary">Envoyer</button>
<div v-if="success" class="alert alert-success mt-3">
Votre réponse a bien été envoyée !
</div>
</form>
</div>
</div>
<div v-if="comment.hasReply">
<div style="margin-left: 30px;">
<comment v-for="comment in comments"
:key="comment.id"
:comment="comment" #remove-comment="remove"
:is-selected="selectedItem" #selected="handleSelected($event)">
</comment>
</div>
</div>
</div>
</template>
<script>
import comment from './CommentItem'
export default {
name: 'comment',
props: {
isSelected: Number,
comment: {
required: true,
type: Object,
}
},
data () {
return {
comments: null,
fields: {},
errors: {},
success: false,
loaded: true,
selectedItem: null,
}
},
computed: {
iAmSelected () {
return this.isSelected === this.comment.id;
}
},
methods: {
remove(id) {
this.$emit('remove-comment', id)
},
toggle(id) {
this.$emit('selected', id);
},
handleSelected(id) {
if(this.selectedItem === id)
this.selectedItem = null;
else
this.selectedItem = id;
},
},
mounted(){
if (this.comment.hasReply) {
axios.get('/comment/replies/' + this.comment.id)
.then(response => {
this.comments = response.data
})
}
}
}
</script>
Thanks in advance for your help!

File (not image) doc/pdf is not uploaded in vue and laravel

I'm trying to upload a pdf /doc file using VUE and laravel but after submitting, The file shows no value.
I have a VUE component with this form and this script:
export default {
data: function() {
return {
product_list: false,
add_form: true,
edit_form: false,
form: {
po_order_docs: '',
},
errors: {},
};
},
methods: {
processFile() {
this.file = _this.$refs.file.files[0];
let formData = new FormData();
formData.append('this.form.po_order_docs', this.file);
},
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.js"></script>
<label class="col-lg-2 col-form-label">Order Docs</label>
<div class="col-lg-4">
<div class="input-group">
<input type="file" class="custom-file-input m-input" id="file" #change="processFile()" ref="file" />
<label class="custom-file-label" for="file">Choose file</label>
</div>
</div>

How to include new component in axios response

I have an component with text input. After fill input and submit form i sand axios query and after response i need stay on the same page with error popup or include new component with response data.
my component
<template>
<div class="col-md-12">
<div class="form-container">
<form v-on:submit="prepareCollage()" class="main-form">
<div class="form-group">
<input type="hidden" name="_token" value="">
<input placeholder="your text" v-model="text" name="query" type="text" class="form-control">
</div>
<button class="go btn btn-primary">Go!</button>
</form>
</div>
</div>
</template>
<script>
export default {
data () {
return {
text : '',
}
},
methods: {
prepareCollage(){
event.preventDefault();
axios.get('/api/prepare?query='+encodeURIComponent(this.text))
.then(function(result){
const result_data = result.data;
// if controller gave an error
if(result_data.error === true){
let error_text = result_data.error_text;
if(typeof(result_data.with_link) != 'undefined' && result_data.with_link.length > 0){
error_text += "<a href='"+result_data.with_link+"'>"+result_data.link_text+"</a>";
}
Vue.swal({
title: 'Error!',
html: error_text,
type: 'error',
})
}else{
// here i need include new component
}
});
}
}
}
</script>
in "else" block i have to include new vue component with data from this component. I have never used vuejs and have difficulty with understand this.

Redirection from a vue component to a laravel route

I have a Vue component named searchbox and I want the users to get redirected to display the results once they type the name and click the search button. I am using axios to make the http request. Here's my template:
<form #submit.prevent="searchResult">
<div class="field has-addons searchbox">
<div class="control">
<input class="input" type="text" id="search" name="q" placeholder="Search a video..." #keyup.enter="searchResult" v-model="searchData">
</div>
<div class="control">
<button class="button is-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</form>
Here's my script in the Vue file:
<script>
export default {
data() {
return {
searchData: null,
};
},
methods: {
searchResult() {
axios.get('/search?q=' + this.searchData);
}
}
}
</script>
Here's my search controller:
class SearchController extends Controller {
public function index(Request $request) {
return view('search.index');
}
}
However, I can not see the redirection. How do I redirect from vue component to another route in laravel??
Is vue-router necessary or we can follow any other method??
you can replace axios.get('/search?q=' + this.searchData); with window.location.href = '/search?q=' + this.searchData;

Resources