summernote / react-summernote

Summernote (Super simple WYSIWYG editor) adaptation for react
http://summernote.org
MIT License
230 stars 108 forks source link

Image upload doesn't work with redux #38

Open Gukulkan opened 6 years ago

Gukulkan commented 6 years ago

Hi

 <ReactSummernote
      value={this.props.currentPost.text}
         options={{
                lang: 'ru-RU',
                   height: 350,
                dialogsInBody: true,
                  toolbar: [
                               ['style', ['style']],
                                 ['font', ['bold', 'underline', 'clear']],
                                 ['fontname', ['fontname']],
                                ['para', ['ul', 'ol', 'paragraph']],
                                 ['table', ['table']],
                                 ['insert', ['link', 'picture', 'video']],
                                 ['view', ['fullscreen', 'codeview']]
                           ]
                   }}
       onChange={this.onChange.bind(this, "text")}
  />

Use the simple example. All text and inserts like tables and lists work good, but imageUpload, I mean base64 uploader doesn't work at all.

Could you help with this? Thanks

Dunkat commented 6 years ago

There is onImageUpload function, where you can insert image as a base64


<ReactSummernote
      value={this.props.currentPost.text}
         options={{
                   height: 350,
                dialogsInBody: true,
                  toolbar: [
                               ['style', ['style']],
                                 ['font', ['bold', 'underline', 'clear']],
                                 ['fontname', ['fontname']],
                                ['para', ['ul', 'ol', 'paragraph']],
                                 ['table', ['table']],
                                 ['insert', ['link', 'picture', 'video']],
                                 ['view', ['fullscreen', 'codeview']]
                           ]
                   }}
       onChange={this.onChange.bind(this, "text")}
       onImageUpload={this.onImageUpload}
  />

 onImageUpload = (fileList) => {

    const reader = new FileReader();
    reader.onloadend = () => {
        ReactSummernote.insertImage(reader.result);
    }
    reader.readAsDataURL(fileList[0]);

}
Dashue commented 6 years ago

For anyone else coming here @Dunkat give a working solution. The reason this doesn't work by default (as it does with summernote without react) is because the react-summernote doesn't support it.

onImageUpload(images) {  
    const { onImageUpload } = this.props;

    if (typeof onImageUpload === 'function') {
        onImageUpload(images, this.insertImage);
    }
}

There should be an else to this if

else {
    /* Custom code to insert images as base64enc instead of uploading to server */
    this.editor.summernote('insertImages', images);
}

Summernote exposes both 'insertImage' and 'insertImages', where the latter takes a list of file objects.

Editor.prototype.insertImages = function (files) {
    var _this = this;
    $$1.each(files, function (idx, file) {
        var filename = file.name;
        if (_this.options.maximumImageFileSize && _this.options.maximumImageFileSize < file.size) {
            _this.context.triggerEvent('image.upload.error', _this.lang.image.maximumFileSizeError);
        }
        else {
            readFileAsDataURL(file).then(function (dataURL) {
                return _this.insertImage(dataURL, filename);
            }).fail(function () {
                _this.context.triggerEvent('image.upload.error');
            });
        }
    });
};

There are good reasons to not insert images as base64enc, but instead having a separate image upload and just including the url. That being said, I think it should provide a helpful starting point for images as a happy path. Not everyone have the time to dig around implementation of summernote :)

Dashue commented 6 years ago

Also I think it's worth mentioning that the solution provided by @Dunkat doesn't seem to work for multiple summernotes on the same page ,as images gets added to the last summernote and not for the editor they were inserted into. It turns out the onImageUpload callback, actually gives back two params, files and a referene to the current editors imageInsert method. I got it working in the end with this:

const onImageUpload = (images: FileList, insertImage) => {
        /* FileList does not support ordinary array methods */
        for (var i = 0; i < images.length; i++) {
            /* Stores as bas64enc string in the text.
             * Should potentially be stored separately and include just the url
             */
            const reader = new FileReader();
            reader.onloadend = () => {
                insertImage(reader.result);
            }
            reader.readAsDataURL(images[i]);
        }
    }
burtonator commented 5 years ago

Ah.. this is a big issue as image support is a huge feature for summernote.

Would love to see this officially fixed.. probably just going to use the default summernote as our own react component for now.

burtonator commented 5 years ago

@Dunkat and @Dashue provided good workarounds for this.. here's my resulting component for other people. Thanks you guys!


class RichTextEditor extends Component {

    onChange(content) {
        console.log('onChange', content);
    }

    onImageUpload(images, insertImage) {

        console.log('onImageUpload', images);
        /* FileList does not support ordinary array methods */
        for (let i = 0; i < images.length; i++) {
            /* Stores as bas64enc string in the text.
             * Should potentially be stored separately and include just the url
             */
            const reader = new FileReader();

            reader.onloadend = () => {
                insertImage(reader.result);
            };

            reader.readAsDataURL(images[i]);
        }
    };

    render() {

        // https://github.com/summernote/react-summernote/issues/38
        //

        return (
            <ReactSummernote
                value=""
                options={{
                    lang: 'en-US',
                    height: 150,
                    dialogsInBody: true,
                    // toolbar: [
                    //     ['style', ['style']],
                    //     ['font', ['bold', 'underline', 'clear']],
                    //     ['fontname', ['fontname']],
                    //     ['para', ['ul', 'ol', 'paragraph']],
                    //     ['table', ['table']],
                    //     ['insert', ['link', 'picture', 'video']],
                    //     ['view', ['fullscreen', 'codeview']]
                    // ]
                }}
                onChange={this.onChange}
                onImageUpload={this.onImageUpload}
            />
        );
    }
}
france05-max commented 4 years ago
   <ReactSummernote
                                name="technicalSpecs"
                                id="technicalSpecs"
                                value={product.technicalSpecs}
                                options={{
                                    lang: 'en',
                                    height: 350,
                                    popover: {},
                                    //dialogsInBody: true,
                                    toolbar: [
                                        ['style', ['style']],
                                        ['font', ['bold', 'underline', 'clear', 'italic']],
                                        ['fontname', ['fontname']],
                                        ['para', ['ul', 'ol', 'paragraph']],
                                        ['table', ['table']],
                                        ['insert', ['link', 'picture', 'video']],
                                        ['view', ['fullscreen', 'codeview']]
                                    ]
                                }}
                                onChange={this.technicalSpecs}
                                onImageUpload={this.technicalSpecsUpload}
                            />
<ReactSummernote
                                name="description"
                                id="description"
                                value={product.description}
                                options={{
                                    lang: 'en',
                                    height: 350,
                                    popover: {},
                                    //dialogsInBody: true,
                                    toolbar: [
                                        ['style', ['style']],
                                        ['font', ['bold', 'underline', 'clear', 'italic']],
                                        ['fontname', ['fontname']],
                                        ['para', ['ul', 'ol', 'paragraph']],
                                        ['table', ['table']],
                                        ['insert', ['link', 'picture', 'video']],
                                        ['view', ['fullscreen', 'codeview']]
                                    ]
                                }}
                                onChange={this.description}
                                onImageUpload={this.descriptionUpload}
                            />
` //react-summernote on image upload
    descriptionUpload = (fileList) => {
        const reader = new FileReader();
        reader.onloadend = () => {
            ReactSummernote.insertImage(reader.result);
        }
        console.log(reader.onloadend)
        reader.readAsDataURL(fileList[0]);

    }
//react-summernote on image upload specs
technicalSpecsUpload = (fileListSpecs) => {
    const reader = new FileReader();
    reader.onloadend = () => {
        ReactSummernote.insertImage(reader.result);
    }
    console.log(reader.onloadend)
    reader.readAsDataURL(fileListSpecs[0]);   

}`
france05-max commented 4 years ago

I have a two react-summernote in one component, everytime i upload a image on technicalspecs the image will go the description . someone can help with this error ? btw the description its already good only technical specs .