Reputation: 15
This is my second question in Stack Overflow. As mentioned in the previous one, I'm working on my project which allow users to upload many images at a time. Each image will be showed as a set of thumpnails. Before uploading, users can delete image(s) he/she doesn't want. Finally, all the images selected and previewed will be stored using data from Vue.js. Thank you @tamrat for his great guidance for that.
This time, I want to create an edit page. It will show the current value of each 'Repair Ticket' such as 'request subject', 'request details', and its 'photos'. As always, you can edit those data and update the latest data. I decided to use Vue.js which allow users to store many images. However, I'm very new about using Vue.js in Laravel.
For now, I'm trying to pass a variable which is '$repair_ticket' from the Controller to view which I set an edit form using Vue.js. I want to show the current data of this '$repair_ticket' which are '$repair_ticket->request_subject', '$repair_ticket->request_details', and 'repair_ticket->photos'.
For the first two value; which are '$repair_ticket->request_subject' and '$repair_ticket->request_details', I'm trying to use 'v-bind:value="@{{$repair_ticket->request_subject}}"' and 'v-bind:value="@{{$repair_ticket->request_details}}"' in the input and textarea corresponsingly. However, it seems there's something wrong. Now, I can't show the current data of these two.
For the last value which is the path file of photos 'repair_ticket->photos', I'm trying to display the current set of photos, but I don't know the way to pass the variable '$repair_ticket' and display it in View using Vue.js
Here is some part of the code in my Vue.js :
<template>
<div class="row justify-content-center">
<div class="col-md-12">
<div class="card-header">Edit Request Form</div>
<div class="card-body">
<form class="vue-form" @submit.prevent="submit">
<fieldset>
<div class="form-group row rounded">
<label class="col-md-4 col-form-label text-md-right" for="request_subject">Request Subject<span style="color: red;">*</span></label>
<input class="col-md-6 form-control" type="text" name="request_subject" id="request_subject" required v-model="request_subject">
</div>
<div class="form-group row rounded">
<label class="col-md-4 col-form-label text-md-right" for="request_details">Request Details</label>
<textarea class="col-md-6 form-control" name="request_details" id="request_details" v-model="request_details" placeholder="Please leave your Request Details Here"></textarea>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label text-md-right" for="photos">Photo</label>
<input class="col-md-6 form-control" ref="photoUploadInput" type="file" multiple @change="handleFileSelect" style="display: none;">
<div class="col-md-6">
<div class="flex justify-between items-center mb-6">
<div class="leading-tight">
<div v-if="photos.length > 0">
<p>You have selected {{ photos.length }} photo(s)</p>
</div>
</div>
<button @click="clickInput" type="button" class="px-6 py-2 font-semibold rounded">Please Choose Your Photo(s)</button>
</div>
<div v-if="photos.length" class="-my-2 -mx-2 flex">
<div v-for="(photo, index) in photos" :key="`thumb-${index}`">
<div class="p-1">
<div class="relative d-flex">
<div class="inset-0" style="vertical-align: middle;">
<img class="object-cover" style="width: 50%;" :src="photo.preview" alt="Your Selected Photo">
<button @click="removePhoto(index)" type="button" class="rounded">
<i class="fas fa-minus" style="color: red;"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="form-group row mb-0 justify-content-center">
<button @click="upload" type="button" :disabled="!request_subject.length" :class="!request_subject.length ? 'cursor-not-allowed bg-gray-600 hover:bg-gray-600' : 'bg-indigo-500 hover:bg-indigo-600'" class="px-6 py-2 font-semibold rounded">Edit Request Form</button>
</div>
</fieldset>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
request_subject: "",
request_details: "",
photos: []
}
},
methods: {
handleFileSelect(e) {
Array.from(e.target.files).forEach(file => {
const reader = new FileReader()
reader.onload = () => {
this.photos.push({
preview: reader.result,
file
})
}
reader.readAsDataURL(file)
})
},
clickInput() {
this.$refs.photoUploadInput.click()
},
upload() {
const dt = new DataTransfer()
this.photos.forEach(photo => dt.items.add(photo.file))
const fd = new FormData()
fd.append('request_subject', document.getElementById('request_subject').value);
fd.append('request_details', document.getElementById('request_details').value);
this.photos.forEach((photo, index) => fd.append(`photo-${index}`, photo.file))
axios.post('upload', fd, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
// .then(response => console.log(response))
.then(response => {
console.log(response);
window.location = 'view-all';
})
.catch(err => console.log(err))
},
removePhoto(index) {
this.photos.splice(index, 1);
}
}
}
</script>
I'm not sure that this is the right way to do it or not. If anyone has any suggestion, please leave your answers below.
UPDATE : I have updated my code in Vue.js as below:
<template>
<div class="row justify-content-center">
<div class="col-md-12">
<div class="card-header">Edit Request Form</div>
<div class="card-body">
<form class="vue-form" @submit.prevent="submit">
<fieldset>
<div class="form-group row rounded">
<label class="col-md-4 col-form-label text-md-right" for="request_subject">ชื่อเรื่อง<span style="color: red;">*</span></label>
<input class="col-md-6 form-control" type="text" name="request_subject" id="request_subject" required :value="repair_ticket['request_subject']">
</div>
<div class="form-group row rounded">
<label class="col-md-4 col-form-label text-md-right" for="request_details">รายละเอียด</label>
<textarea class="col-md-6 form-control" name="request_details" id="request_details" :value="repair_ticket['request_details']"></textarea>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label text-md-right" for="photos">Photos</label>
<input class="col-md-6 form-control" ref="photoUploadInput" type="file" multiple @change="handleFileSelect" style="display: none;">
<div class="col-md-6">
<div class="flex justify-between items-center mb-6">
<div class="leading-tight">
<div v-if="photos.length > 0">
<p>You have selected {{ photos.length }} photo(s)</p>
</div>
</div>
<button @click="clickInput" type="button" class="px-6 py-2 font-semibold rounded">Please choose photo(s)</button>
</div>
<div v-if="photos.length" class="-my-2 -mx-2 flex">
<div v-for="(photo, index) in photos" :key="`thumb-${index}`">
<div class="p-1">
<div class="relative d-flex">
<div class="inset-0" style="vertical-align: middle;">
<img class="object-cover" style="width: 50%;" :src="photo.preview" alt="Selected Photo">
<button @click="removePhoto(index)" type="button" class="rounded">
<i class="fas fa-minus" style="color: red;"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="form-group row mb-0 justify-content-center">
<button @click="upload" type="button" class="px-6 py-2 font-semibold rounded">Edit Request Form</button>
</div>
</fieldset>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['repair_ticket'],
mounted() {
console.log(this.repair_ticket)
},
data() {
return {
repair_ticket_id: this.repair_ticket.id,
request_subject: "",
request_details: "",
photos: []
}
},
methods: {
handleFileSelect(e) {
Array.from(e.target.files).forEach(file => {
const reader = new FileReader()
reader.onload = () => {
this.photos.push({
preview: reader.result,
file
})
}
reader.readAsDataURL(file)
})
},
clickInput() {
this.$refs.photoUploadInput.click()
},
upload() {
const dt = new DataTransfer()
this.photos.forEach(photo => dt.items.add(photo.file))
const fd = new FormData()
fd.append('repair_ticket_id', this.repair_ticket_id);
fd.append('request_subject', document.getElementById('request_subject').value);
fd.append('request_details', document.getElementById('request_details').value);
this.photos.forEach((photo, index) => fd.append(`photo-${index}`, photo.file))
axios.put('re-upload/' + this.repair_ticket.id, fd, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
// .then(response => console.log(response))
.then(response => {
console.log(response);
window.location = 'view-all';
})
.catch(err => console.log(err))
},
removePhoto(index) {
this.photos.splice(index, 1);
}
}
}
</script>
I have set route for this like below:
Route::put('irepair/edit-form/re-upload/{id}', 'iRepair\RequestFormsController@update');
For now, I can show the current data of 'request_subject' and 'request_details', but still cannot show the current photos of this repair ticket. Also, I still stuck on sending data to the controller and update the data the the database according to what changed. It keep saying Error 405.
Anyone has any suggestions for this? Please leave your answers below.
Upvotes: 1
Views: 1665
Reputation: 1801
You can use Vue props. hope this help you
inside laravel blade
<edit-ticket :repair-ticket="{{ json_encode($repair_ticket) }}"></edit-ticket>
Vue Component
export default {
props:['repairTicket'],
mounted() {
console.log(this.repairTicket)
}
}
Upvotes: 1