I am using admin-on-rest and react-tinymce. When I include file_picker_callback in the tinymce config the editor will reload every time the onchange event fires.
This is an issue because users are not able to continually type (editor loses focus after reloading). I have tried manually setting the focus after it reloads, but it does not focus back to the same place the cursor was previously - so this is not a viable workaround.
If I remove the file_picker_callback, then everything works as expected.
Here is my code:
import React, { PropTypes, Component } from 'react'
import TinyMCE from 'react-tinymce'
import debounce from 'lodash.debounce';
class Editor extends Component {
self;
componentDidMount() {
const {
id,
disabled,
label,
name,
input: {
value,
onChange
},
config
} = this.props;
self = this;
}
onEditorChange = (content = window.tinyMCE.activeEditor.getContent()) => {
if (self.props.input.value == content)
return;
self.props.input.onChange(content);
}
render() {
return (
<div>
<input type="file" id="image-upload-tinymce" name="single-image" style={{ display: "none" }} accept="image/png, image/gif, image/jpeg, image/jpg, image/svg" />
<TinyMCE
content={this.props.input.value}
config={{
plugins: [
'advlist autolink lists link image charmap print preview anchor',
'searchreplace wordcount visualblocks code',
'insertdatetime table contextmenu paste code'
],
toolbar: 'insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | code',
file_browser_callback_types: 'image',
file_picker_callback: (callback, value, meta) => {
if (meta.filetype == 'image') {
var input = document.getElementById('image-upload-tinymce');
input.click();
input.onchange = () => {
var file = input.files[0];
var reader = new FileReader();
reader.onload = (e) => {
var img = new Image();
img.src = reader.result;
callback(e.target.result, {
alt: file.name
});
var delay = debounce(self.onEditorChange, 10000);
delay();
};
reader.readAsDataURL(file);
};
}
},
}}
id={this.props.id}
onKeyup={e => {
e.stopPropagation();
e.preventDefault();
var delay = debounce(self.onEditorChange, 500);
delay();
}}
/>
</div>
)
}
}
I have the following in my index.html:
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.6/tinymce.min.js"></script>
What I have noticed is that during an onchange event there is a get request issued for:
https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.6/skins/lightgray/content.min.css
and the call stack for this request is as follows:
initContentBody @ tinymce.min.js:11
init @ tinymce.min.js:11
(anonymous) @ tinymce.min.js:11
(anonymous) @ tinymce.min.js:4
n @ tinymce.min.js:3
v @ tinymce.min.js:4
loadScripts @ tinymce.min.js:4
loadQueue @ tinymce.min.js:4
t @ tinymce.min.js:11
render @ tinymce.min.js:11
a @ tinymce.min.js:12
(anonymous) @ tinymce.min.js:12
n @ tinymce.min.js:3
d @ tinymce.min.js:12
t.bind @ tinymce.min.js:2
bind @ tinymce.min.js:4
init @ tinymce.min.js:12
_init @ TinyMCE.js:128
TinyMCE_componentWillReceiveProps @ TinyMCE.js:66
(anonymous) @ ReactCompositeComponent.js:611
measureLifeCyclePerf @ ReactCompositeComponent.js:75
updateComponent @ ReactCompositeComponent.js:610
receiveComponent @ ReactCompositeComponent.js:547
receiveComponent @ ReactReconciler.js:125
updateChildren @ ReactChildReconciler.js:109
_reconcilerUpdateChildren @ ReactMultiChild.js:208
_updateChildren @ ReactMultiChild.js:312
updateChildren @ ReactMultiChild.js:299
_updateDOMChildren @ ReactDOMComponent.js:936
updateComponent @ ReactDOMComponent.js:754
receiveComponent @ ReactDOMComponent.js:716
receiveComponent @ ReactReconciler.js:125
_updateRenderedComponent @ ReactCompositeComponent.js:754
_performComponentUpdate @ ReactCompositeComponent.js:724
updateComponent @ ReactCompositeComponent.js:645
receiveComponent @ ReactCompositeComponent.js:547
receiveComponent @ ReactReconciler.js:125
updateChildren @ ReactChildReconciler.js:109
_reconcilerUpdateChildren @ ReactMultiChild.js:208
_updateChildren @ ReactMultiChild.js:312
updateChildren @ ReactMultiChild.js:299
_updateDOMChildren @ ReactDOMComponent.js:936
updateComponent @ ReactDOMComponent.js:754
receiveComponent @ ReactDOMComponent.js:716
receiveComponent @ ReactReconciler.js:125
_updateRenderedComponent @ ReactCompositeComponent.js:754
_performComponentUpdate @ ReactCompositeComponent.js:724
updateComponent @ ReactCompositeComponent.js:645
receiveComponent @ ReactCompositeComponent.js:547
receiveComponent @ ReactReconciler.js:125
_updateRenderedComponent @ ReactCompositeComponent.js:754
_performComponentUpdate @ ReactCompositeComponent.js:724
updateComponent @ ReactCompositeComponent.js:645
receiveComponent @ ReactCompositeComponent.js:547
receiveComponent @ ReactReconciler.js:125
_updateRenderedComponent @ ReactCompositeComponent.js:754
_performComponentUpdate @ ReactCompositeComponent.js:724
updateComponent @ ReactCompositeComponent.js:645
receiveComponent @ ReactCompositeComponent.js:547
receiveComponent @ ReactReconciler.js:125
_updateRenderedComponent @ ReactCompositeComponent.js:754
_performComponentUpdate @ ReactCompositeComponent.js:724
updateComponent @ ReactCompositeComponent.js:645
performUpdateIfNecessary @ ReactCompositeComponent.js:561
performUpdateIfNecessary @ ReactReconciler.js:157
runBatchedUpdates @ ReactUpdates.js:150
perform @ Transaction.js:140
perform @ Transaction.js:140
perform @ ReactUpdates.js:89
flushBatchedUpdates @ ReactUpdates.js:172
closeAll @ Transaction.js:206
perform @ Transaction.js:153
batchedUpdates @ ReactDefaultBatchingStrategy.js:62
enqueueUpdate @ ReactUpdates.js:200
enqueueUpdate @ ReactUpdateQueue.js:24
enqueueSetState @ ReactUpdateQueue.js:219
ReactComponent.setState @ ReactComponent.js:63
handleChange @ connect.js:302
dispatch @ createStore.js:186
(anonymous) @ middleware.js:22
(anonymous) @ middleware.js:80
boundChange @ createFieldProps.js:97
(anonymous) @ createOnChange.js:37
Editor._this.onEditorChange @ editor.js:29
invokeFunc @ index.js:160
trailingEdge @ index.js:207
timerExpired @ index.js:195
From the call stack, line 66 of TinyMCE.js is:
componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
if (!(0, _lodashLangIsEqual2['default'])(this.props.config, nextProps.config)) {
this._init(nextProps.config, nextProps.content);//line 66 here
}
line 128 is tinymce.init(config);
I believe this is a bug with react-tinymce (and not admin-on-rest) - but I am not very familiar with react, so I could be wrong.
Any help or insight would be appreciated. I have spent 2 days debugging this and have made no progress
I am using admin-on-rest and react-tinymce. When I include
file_picker_callbackin the tinymce config the editor will reload every time the onchange event fires.This is an issue because users are not able to continually type (editor loses focus after reloading). I have tried manually setting the focus after it reloads, but it does not focus back to the same place the cursor was previously - so this is not a viable workaround.
If I remove the
file_picker_callback, then everything works as expected.Here is my code:
I have the following in my index.html:
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.6/tinymce.min.js"></script>What I have noticed is that during an onchange event there is a get request issued for:
https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.6/skins/lightgray/content.min.cssand the call stack for this request is as follows:
From the call stack, line 66 of TinyMCE.js is:
line 128 is
tinymce.init(config);I believe this is a bug with react-tinymce (and not admin-on-rest) - but I am not very familiar with react, so I could be wrong.
Any help or insight would be appreciated. I have spent 2 days debugging this and have made no progress