vue-quill-editor uploads pictures to the server

Released 2018-01-13

vue-quill-editor-upload : Implement vue-quill-editor to upload pictures to the server

install

  • npm

    npm install vue-quill-editor-upload –save

<template>
  <!-- bidirectional data binding (two-way data binding) -->
  <quill-editor v-model="content"
                ref="myQuillEditor"
                :options="editorOption">
  </quill-editor>
</template>

<script>
  import {quillRedefine} from 'vue-quill-editor-upload'
  import {quillEditor} from 'vue-quill-editor'
  export default {
    components: {quillEditor, quillRedefine},
    data () {
      return {
        content: '',
        editorOption: {} // must be initialized as an object init to Object
      }
    },
    created () {
      this.editorOption = quillRedefine(
        {
          // Settings for image upload
          uploadConfig: {
            action: '', // required parameter image upload address
            // The required parameter res is a function, and the response received by the function is the data returned by the server when the upload is successful
            // You must return the image address contained in the returned data
            res: (respnse) => {
              return respnse.info
            },
            name: 'img' // image upload parameter name
          }
        }
      )
      console. log(this. editorOption)
    }
  }
</script>

use

You have to install vue-quill-editor first.

Make sure you have vue-quill-editor installed

import

import {quillRedefine} from ‘vue-quill-editor-upload’

quillRedefine is a function

All parameters that quillRedefine can accept (all params)

{
          // Settings for image upload
          uploadConfig: {
            action: '', // required parameter image upload address
            // The required parameter res is a function, and the response received by the function is the data returned by the server when the upload is successful
            // You must return the image address contained in the returned data
            res: (respnse) => {
              return respnse.info
            },
            methods: 'POST', // optional parameter image upload method, the default is post
            token: sessionStorage.token, // optional parameter If token verification is required, assuming your token is stored in sessionStorage
            name: 'img', // optional parameter file parameter name, the default is img
            size: 500, // optional parameter image limit size, unit is Kb, 1M = 1024Kb
            accept: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon', // optional parameter uploadable image format
            // start: function (){}
            start: () => { }, // Optional parameter receives a function that will be triggered when uploading data starts
            end: () => { }, // Optional parameter Receives a function that will be triggered when the upload data is completed (success or failure)
            success: () => {}, // Optional parameter receives a function that will be triggered when uploading data is successful
            error: () => { } // Optional parameter Receives a function that will be triggered when uploading data is interrupted
          },
          // All the following settings correspond to vue-quill-editor itself
          placeholder: '', // optional parameter prompt in the rich text box
          theme: '', // optional parameter rich text editor style
          toolOptions: [], // optional parameters to select which functions are required for the toolbar, the default is all
          handlers: {} // optional parameters redefined events, such as link and other events
}
  • demo

first

you must to do: :options=”editorOption” to bound Parameters

You have to bind option :options=”editorOption”

<template>
  <!-- bidirectional data binding (two-way data binding) -->
  <quill-editor
                :options="editorOption">
  </quill-editor>
</template>

second

return editorOption

must write editorOPtion in return and set default to empty object

 data () {
      return {
        content: '',
        editorOption: {} // must be initialized as an object init to Object
      }
    }

three

init in created

Generate actual data in the created life cycle

created () {
      this.editorOption = quillRedefine(
        {
          // Settings for image upload
          uploadConfig: {
            action: '', // required parameter image upload address
            // The required parameter res is a function, and the response received by the function is the data returned by the server when the upload is successful
            // You must return the image address contained in the returned data
            res: (respnse) => {
              return respnse.info // Remember to return your picture address here
            }
          }
        }
      )
     // console. log(this. editorOption)
    }

Matters need attention

Because the data format returned by the server of different users is not the same

therefore

In uploadConfig you have to do as follows

 // You must return the image address contained in the returned data
 res: (respnse) => {
    return respnse.info // Remember to return your picture address here
 }

For example, the success data returned by your server is

{
code: 200,
starus: true,
result: {
    img: 'http://placehold.it/100x100' // The address of the picture in the data returned by the server
 }
}

Then you should write in parameters as:

 // You must return the image address contained in the returned data
 res: (respnse) => {
    return respnse.result.img // Remember to return your image address here
 }

example

complete use case

<template>
  <!-- bidirectional data binding (two-way data binding) -->
  <quill-editor v-model="content"
                ref="myQuillEditor"
                :options="editorOption">
  </quill-editor>
</template>

<script>
  import {quillRedefine} from 'vue-quill-editor-upload'
  import {quillEditor} from 'vue-quill-editor'
  export default {
    components: {quillEditor, quillRedefine},
    data () {
      return {
        content: '',
        editorOption: {} // must be initialized as an object init to Object
      }
    },
    created () {
      this.editorOption = quillRedefine(
        {
          // Settings for image upload
          uploadConfig: {
            action: '', // required parameter image upload address
            // The required parameter res is a function, and the response received by the function is the data returned by the server when the upload is successful
            // You must return the image address contained in the returned data
            res: (respnse) => {
              return respnse.info
            },
            methods: 'POST', // optional parameter image upload method, the default is post
            token: sessionStorage.token, // optional parameter If token verification is required, assuming your token is stored in sessionStorage
            name: 'img', // optional parameter file parameter name, the default is img
            size: 500, // optional parameter image limit size, unit is Kb, 1M = 1024Kb
            accept: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon', // optional parameter uploadable image format
            // start: function (){}
            start: () => {
            }, // Optional parameter receives a function that will be triggered when uploading data starts
            end: () => {
            }, // Optional parameter receives a function that will be triggered when the upload data is completed (success or failure)
            success: () => {
            }, // Optional parameter to receive a function that will be triggered when uploading data is successful
            error: () => {
            } // Optional parameter to receive a function that will be triggered when uploading data is interrupted
          },
          // All the following settings correspond to vue-quill-editor itself
          placeholder: '', // optional parameter prompt in the rich text box
          theme: '', // optional parameter rich text editor style
          toolOptions: [], // optional parameters to select which functions are required for the toolbar, the default is all
          handlers: {} // optional parameters redefined events, such as link and other events
        }
      )
      console. log(this. editorOption)
    }
  }
</script>

The code above is what I moved from other places. The code below is mine. You can combine it according to my code.

I think the most important point is to copy and paste blindly, because developers will be impatient if they can’t write it out, so they should take all considerations into account and then operate

<template>
    <div id="articleAdd">
        <div class="search">
            <el-form label-width="80px">
                <el-form-item label="title">
                    <el-input clearable placeholder="Please enter a title" v-model="form.title"></el-input>
                </el-form-item>

                <el-form-item label="Author">
                    <el-input clearable="clearable" placeholder="Please enter the author" v-model="form.author"></el-input>
                </el-form-item>

                <el-form-item label="weight">
                    <el-input clearable="clearable" placeholder="Please enter the weight" v-model="form.sort"></el-input>
                </el-form-item>

                <el-form-item label="Cover">
                    <el-upload class="upload-demo" :action="uploadUrl" :data="prefix" :file-list="coverBox"
                        :on-remove="handleRemove" :on-success="handleAvatarSuccess"
                        list-type="picture">
                        <el-button size="small" type="primary">Click to upload</el-button>
                    </el-upload>
                </el-form-item>
                <el-form-item label="upload type">
                    <el-radio-group v-model="upLoadType">
                        <el-radio:label="1">Upload link</el-radio>
                        <el-radio:label="2">Upload articles</el-radio>
                    </el-radio-group>
                </el-form-item>

            </el-form>
            
        </div>

        <!-- Picture upload component auxiliary -->
        <el-upload
            class="avatar-uploader"
            :action="uploadUrl" type="drag"
            :data="prefix"
            :show-file-list="false"
            :on-success="uploadSuccess"
            :on-error="uploadError"
            :before-upload="beforeUpload">
        </el-upload>

        <el-form label-width="80px">
        <!--Rich Text Editor Component-->
            <el-form-item label="upload address" v-if="upLoadType == 1">
                <el-input clearable placeholder="Please enter the upload address" v-model="form.url"></el-input>
            </el-form-item>

            <el-form-item label="upload content" v-if="upLoadType == 2" v-loading="uillUpdateImg">
                <quill-editor
                    v-model="form. content"
                    ref="myQuillEditor"
                    :options="editorOption"
                    @focus="onEditorFocus($event)"
                    @change="onEditorChange($event)">
                </quill-editor>
            </el-form-item>
        </el-form>

        <el-button type="primary" class="subMit" @click="submitBtn"
            :disabled="!(Boolean(form.title) & amp; & amp; Boolean(form.author) & amp; & amp; Boolean(form.cover) & amp; & amp; Boolean(form.sort))" >Submit</el-button>
        <!-- <div class="ql-container ql-snow">
            <div class="ql-editor">
                <div v-html="detailContent"></div>
            </div>
        </div> -->
    </div>
</template>
<script>
    import { subBtnFn, getInfoFn } from 'api/game/find/articleAdd';
    import { toolbarOptions } from 'api/game/find/toolbarOptions'; // toolbar configuration
    import { quillEditor } from "vue-quill-editor"; //call the editor
    import 'quill/dist/quill.core.css';
    import 'quill/dist/quill.snow.css';
    import 'quill/dist/quill.bubble.css';

    export default {
        components: { quillEditor }, // register components
        data() {
            return {
                uillUpdateImg: false,
                uploadUrl: undefined,
                coverBox: [],
                prefix: {prefix: 'contest'}, // Alibaba Cloud additional parameters
                upLoadType: 1, // 1 is URL and 2 is content
                form: {
                    id: undefined, // article id
                    moduleId: undefined, // module id
                    title: undefined, // title
                    author: undefined, // author
                    cover: undefined, // cover
                    status: 1, // status 1: banned, 2: normal
                    sort: undefined, // weight
                    url: undefined, // link address
                    content: undefined, // body content
                },
                editorOption: {
                    theme: 'snow', // or 'bubble'
                    modules: {
                        toolbar: {
                            container: toolbarOptions, // toolbar
                            handlers: {
                                'image': function (value) {
                                    if (value) {
                                        // Trigger the input box to select the image file
                                        document.querySelector('.avatar-uploader input').click()
                                    } else {
                                        this.quill.format('image', false);
                                    }
                                }
                            }
                        }
                    }
                },
            }
        },
        created () {
            this.uploadUrl = this.defaultUploadUrl;
            if (this.$route.query){ // determine whether there is a value
                this.form.moduleId = this.$route.query.moduleId;
                if (this.$route.query.id) { // determine whether it is an edit
                    this.form.id = this.$route.query.id;
                    this. getData();
                }
            }
        },
        methods: {
            getData() {
                this. coverBox = []
                getInfoFn({ id: this.form.id }).then(res=>{
                    if (res. code == 0) {
                        this.form = {...res.data};
                        if (res.data.url) { // 1 is URL 2 is content
                            this.upLoadType = 1;
                        } else {
                            this.upLoadType = 2;
                        }
                        this.coverBox.push({url: res.data.cover, name: res.data.cover})
                    } else {
                        this.$message.error( res.message );
                    }
                })
            },

            // get focus event
            onEditorFocus(e){ this.lenIndex = e.getSelection().index; },
            // content change event
            onEditorChange(e){ this.lenIndex = e.quill.getSelection().index; },
            escapeStringHTML(str) { // escape code
                str = str.replace(/</g,'<');
                str = str.replace(/>/g,'>');
                return str;
            },
            /* handleSingleSuccess (res, file) { // res is the data returned by the image server
                let quill = this.$refs.myQuillEditor.quill; // get rich text component instance
                if (res. code == '0') {
                    // Insert picture res.info is the picture address returned by the server
                    quill.insertEmbed(this.lenIndex, 'image', res.data)
                    // Adjust the cursor to the end
                    quill.setSelection(this.lenIndex + 1)
                } else {
                    this.$message.error('Picture insertion failed')
                }
                this.quillUpdateImg = false; // loading animation disappears
            }, */


            // Before the rich text image is uploaded
            beforeUpload() { this.quillUpdateImg = true; },
            uploadSuccess(res, file) { // res is the data returned by the image server
                let quill = this.$refs.myQuillEditor.quill;
                if (res. code == 0) {
                    let length = quill.getSelection().index; // Get the position of the cursor
                    quill.insertEmbed(length, 'image', res.data); // insert a picture res.info is the picture address returned by the server
                    quill.setSelection(length + 1); // adjust the cursor to the end
                } else {
                    this.$message.error('Picture insertion failed')
                }
                this.quillUpdateImg = false; // loading animation disappears
            },
            // Rich text image upload failed
            uploadError() {
                // The loading animation disappears
                this.quillUpdateImg = false;
                this.$message.error('Picture insertion failed');
            },
            submitBtn() {
                if (this.upLoadType == 1) { // 1 is URL and 2 is content
                    this.form.content = undefined;
                    if (!this.form.url) {
                        this.$message.error({ message: 'Please fill in the data you want to upload!' });
                        return;
                    }
                } else {
                    this.form.url = undefined;
                    if (!this. form. content) {
                        this.$message.error({ message: 'Please fill in the data you want to upload!' });
                        return;
                    }
                }
                subBtnFn({...this.form}).then(res => {
                    if (res. code == 0) {
                        this.$message({ showClose: true, message: 'The data has been added successfully and will be redirected', type: 'success' });
                        setTimeout(() => {
                            this. $router. push({
                                path: '/find/articleManage',
                                query: {
                                    copywritingId: this.form.moduleId
                                }
                            });
                        }, 1500);
                    }
                })
            },
            // cover upload
            handleAvatarSuccess(res, file) { this. form. cover = res. data; },
            handleRemove (file, fileList) { this. edit. cover = ''; },
        },
    }

</script>
<style>
    #articleAdd {
        margin: 30px;
    }

    #articleAdd .avatar-uploader .el-upload {
        border: 1px dashed #d9d9d9;
        border-radius: 6px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
    }
    #articleAdd .avatar-uploader .el-upload:hover {
        border-color: #409EFF;
    }
    #articleAdd .avatar-uploader-icon {
        font-size: 28px;
        color: #8c939d;
        width: 178px;
        height: 178px;
        line-height: 178px;
        text-align: center;
    }
    #articleAdd.avatar {
        width: 178px;
        height: 178px;
        display: block;
    }
    #articleAdd.subMit {
        /* float: right; */
        margin: 20px 0;
    }
</style>