Livewire Quill Editor Image Upload

Viewed 85

I'm using Quill editor on Livewire and trying to upload inserted images on editor with Livewire JavaScript Upload API. The problem is, I can't insert temporary url to editor. If I use $image->temporaryUrl() or $url outside of editor, image shows. I can get image temporary url. But $image->temporaryUrl() and $url not working inside the editor. And images are still uploading to livewire-tmp directory. Just can't insert temporary url to editor.

My blade file:

<script>
    var quill = null;

    function selectLocalImage() {
        const input = document.createElement('input');
        input.setAttribute('type', 'file');
        input.click();

        // Listen upload local image and save to server
        input.onchange = () => {
            const file = input.files[0];

            // file type is only image.
            if (/^image\//.test(file.type)) {
                imageHandler(file);
            } else {
                console.warn('You could only upload images.');
            }
        };
    }

    function imageHandler(image) {
        var formData = new FormData();
        var url = '{{ $url }}';
        formData.append('image', image);
        formData.append('_token', '{{ csrf_token() }}');
        formData.append('pageId', '{{ $page->id }}');
        //let file = document.querySelector('image').files[0];
        @this.upload('image', image, (uploadedFilename) => {
            insertToEditor(url, quill);
        })
    }

    function insertToEditor(url, editor) {
        // push image url to rich editor.
        const range = editor.getSelection();
        editor.insertEmbed(range.index, 'image', url);
    }

    $(document).ready(function() {
        var options = {
            modules: {
                syntax: true,
                toolbar: [
                    [{
                        'font': []
                    }, {
                        'size': []
                    }],
                    ['bold', 'italic', 'underline', 'strike'],
                    [{
                        'color': []
                    }, {
                        'background': []
                    }],
                    [{
                        'script': 'super'
                    }, {
                        'script': 'sub'
                    }],
                    [{
                        'header': '1'
                    }, {
                        'header': '2'
                    }, 'blockquote', 'code-block'],
                    [{
                        'list': 'ordered'
                    }, {
                        'list': 'bullet'
                    }, {
                        'indent': '-1'
                    }, {
                        'indent': '+1'
                    }],
                    ['direction', {
                        'align': []
                    }],
                    ['link', 'image', 'video', 'formula'],
                    ['clean']
                ]
            },
            placeholder: 'Content...',
            theme: 'snow'
        };
        quill = new Quill('#editor', options);

        quill.getModule('toolbar').addHandler('image', () => {
            selectLocalImage();
        });

        quill.on('text-change', function() {
            @this.set('pageBody', quill.root.innerHTML);
        });
    });
</script>

My component:

public $image;
public $url;
public function updatedImage()
{
    if ($this->image) {
        $this->url = $this->image->temporaryUrl();
        // dd($this->url); <---- Showing temporary url
    }
}

How can I solve this problem?

2 Answers

After some research I've changed my code like below.

After upload, fired an event called imageAdded with image parameter. And listen this event on Livewire component.

With imageAdded function I've defined image's temporary url. And dispatched a browser event called getUrl. With array_push I added new images to $images array. Because there could be multiple images to upload.

Finally, listened dispatched browser event getUrl on Java Script and then added to editor with insertToEditor function.

function imageHandler(image) {
    var formData = new FormData();
    formData.append('image', image);
    formData.append('_token', '{{ csrf_token() }}');
    formData.append('pageId', '{{ $page->id }}');
    @this.upload('image', image, (uploadedFilename) => {
        window.livewire.emit('imageAdded', image);
    });
}

window.addEventListener('getUrl', e => {
    e.detail.imageUrl;
    console.log(e.detail.imageUrl);
    insertToEditor(e.detail.imageUrl, quill);
});

function insertToEditor(url, editor) {
    // push image url to rich editor.
    const range = editor.getSelection();
    editor.insertEmbed(range.index, 'image', url);
}

Component:

public $images = [];
public $image;
public $url;
protected $listeners = ['imageAdded'];

public function imageAdded()
{
    $this->url = $this->image->temporaryUrl();
    $this->dispatchBrowserEvent('getUrl', ['imageUrl' => $this->url]);
    array_push($this->images, $this->image);
}

public function store()
{
    foreach ($this->images as $key => $image) {
        $image->store('images/page_images/'.$this->page->id);
    }    
}

Now I can upload images with Quill editor on Livewire. Suggestions would be pleased.

I've developed this part based in your code. With that you can replace the temporary url by stored images. If you want, you can save regex in variable.

    public function store()
    {
        $this->validate();
        foreach ( $this->images as $key => $image ) {
            
            $temporaryUrl = $image->temporaryUrl();
            preg_match('/(https?:\/\/.*\.(?:png|jpg|gif))/', $temporaryUrl, $tmp);
            if ( $tmp[0] ) {
                $temporaryUrl = $tmp[0];
                $url = $image->store('imgs/help-center');
                $url = config('app.url') . '/' . $url;
                preg_match('/(https?:\/\/.*\.(?:png|jpg|gif))/', $url, $match);
                if ( $match[0] ) {
                    $url = $match[0];
                    $this->article['content'] = str_replace($temporaryUrl, $url, $this->article['content']);
                }
            }
        
        }
        $this->images = [];
        $article = HelpCenter::updateOrCreate([
            'id' => $this->article['id']
        ], $this->article);

    }

i hope it help you

Related