jeudi 15 novembre 2018

Upload Image in Vue Component with Laravel

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.



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire