You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
855 lines
26 KiB
855 lines
26 KiB
*Covered in this section:*
|
|
|
|
* xref:installing-the-tinymce-react-integration-using-npm-or-yarn[Installing the TinyMCE React integration using NPM or Yarn]
|
|
* xref:using-tinymce-react-integration-in-a-bootstrap-dialog[Using TinyMCE React integration in a Bootstrap dialog]
|
|
* xref:configuring-the-editor[Configuring the editor]
|
|
* xref:available-props[Available props]
|
|
** xref:apikey[`+apiKey+`]
|
|
** xref:licenseKey[`+licenseKey+`]
|
|
** xref:cloudchannel[`+cloudChannel+`]
|
|
** xref:disabled[`+disabled+`]
|
|
** xref:id[`+id+`]
|
|
** xref:init[`+init+`]
|
|
** xref:initialvalue[`+initialValue+`]
|
|
** xref:inline[`+inline+`]
|
|
** xref:oneditorchange[`+onEditorChange+`]
|
|
** xref:outputformat[[.line-through]#`+outputFormat+`# (_removed_)]
|
|
** xref:plugins[`+plugins+`]
|
|
** xref:rollback[`+rollback+`]
|
|
** xref:scriptloading[`+scriptLoading+`]
|
|
** xref:tagname[`+tagName+`]
|
|
** xref:textareaname[`+textareaName+`]
|
|
** xref:toolbar[`+toolbar+`]
|
|
** xref:tinymcescriptsrc[`+tinymceScriptSrc+`]
|
|
** xref:value[`+value+`]
|
|
** xref:tabIndex[`+tabIndex+`]
|
|
* xref:using-the-tinymce-react-component-as-a-uncontrolled-component[Using the TinyMCE React component as a uncontrolled component]
|
|
* xref:using-the-tinymce-react-component-as-a-controlled-component[Using the TinyMCE React component as a controlled component]
|
|
* xref:event-binding[Event binding]
|
|
|
|
[[installing-the-tinymce-react-integration-using-npm-or-yarn]]
|
|
== Installing the TinyMCE React integration using NPM or Yarn
|
|
|
|
To install the `+tinymce-react+` package and save it to your `+package.json+`.
|
|
|
|
[source,sh]
|
|
----
|
|
npm install @tinymce/tinymce-react
|
|
----
|
|
|
|
or with Yarn
|
|
|
|
[source,sh]
|
|
----
|
|
yarn add @tinymce/tinymce-react
|
|
----
|
|
|
|
[[using-tinymce-react-integration-in-a-bootstrap-dialog]]
|
|
== Using TinyMCE React integration in a Bootstrap dialog
|
|
|
|
To use the {productname} React integration inside Bootstrap UI dialogs, add the following React effect hook to a component that renders with the editor. This code is required because Bootstrap blocks all `+focusin+` calls from elements outside the dialog.
|
|
|
|
=== Bootstrap 5
|
|
|
|
NOTE: For Bootstrap 5, the React effect hook contains no JQuery.
|
|
|
|
[source,jsx]
|
|
----
|
|
useEffect(() => {
|
|
const handler = (e) => {
|
|
if (e.target.closest(".tox-tinymce-aux, .moxman-window, .tam-assetmanager-root") !== null) {
|
|
e.stopImmediatePropagation();
|
|
}
|
|
};
|
|
document.addEventListener("focusin", handler);
|
|
return () => document.removeEventListener("focusin", handler);
|
|
}, []);
|
|
----
|
|
|
|
=== Bootstrap 4
|
|
|
|
[source,js]
|
|
----
|
|
useEffect(function() {
|
|
var handler = function(e) {
|
|
if ($(e.target).closest(".tox-tinymce, .tox-tinymce-aux, .moxman-window, .tam-assetmanager-root").length) {
|
|
e.stopImmediatePropagation();
|
|
}
|
|
};
|
|
$(document).on('focusin', handler);
|
|
return function() {
|
|
$(document).off('focusin', handler);
|
|
};
|
|
}, []);
|
|
----
|
|
|
|
[[configuring-the-editor]]
|
|
== Configuring the editor
|
|
|
|
The `+tinymce-react+` component provides props for:
|
|
|
|
* xref:configuring-editor-source[Configuring editor source]
|
|
* xref:configuring-page-elements[Configuring page elements]
|
|
* xref:configuring-editor-options[Configuring editor options]
|
|
* xref:managing-the-editor[Managing the editor]
|
|
|
|
[[configuring-editor-source]]
|
|
=== Configuring editor source
|
|
|
|
The `+tinymce-react+` integration will try to source {productname} in the following order:
|
|
|
|
. The global `+tinymce+` will be used, if it is present on the page.
|
|
. If the `+tinymceScriptSrc+` prop is provided, then a script tag will be added to the page to load {productname} from the given URL.
|
|
. If none of the above conditions apply, then a script tag will be added to the page to load {productname} from {cloudname}.
|
|
|
|
These props are used to configure how the editor is sourced:
|
|
|
|
xref:apikey[`+apiKey+`]:: The {cloudname} API key. When loading from {cloudname}, use this prop to remove the "A valid API key is required to continue using TinyMCE. Please alert the admin to check the current API key. Click here to learn more." warning message.
|
|
|
|
xref:licenseKey[`+licenseKey+`]:: The {cloudname} License key. Use this when self-hosting {productname} instead of loading from {cloudname}.
|
|
|
|
xref:cloudchannel[`+cloudChannel+`]:: The channel of {productname} used when loading from {cloudname}.
|
|
|
|
xref:scriptloading[`+scriptLoading+`]:: The script loading behavior prop. Allows setting of the `+async+` and `+defer+` attributes, as well as adding an additional delay in milliseconds.
|
|
|
|
xref:tinymcescriptsrc[`+tinymceScriptSrc+`]:: The URL to use for sourcing {productname}, when loading a self-hosted version of {productname}.
|
|
|
|
[[configuring-page-elements]]
|
|
=== Configuring page elements
|
|
|
|
These props provide some control over the page elements that the integration creates:
|
|
|
|
xref:id[`+id+`]:: The id attribute of the element that the editor is initialized on.
|
|
|
|
xref:inline[`+inline+`]:: Load the editor as part of the page; sharing the page styles and selection.
|
|
|
|
xref:tagname[`+tagName+`]:: The tag used for creating an inline editor. Ignored for a classic (iframe) editor.
|
|
|
|
xref:textareaname[`+textareaName+`]:: The name attribute on the textarea tag (HTML element). Used for creating the classic (iframe) editor. Ignored for an inline editor.
|
|
|
|
[[configuring-editor-options]]
|
|
=== Configuring editor options
|
|
|
|
These props are read when the editor is initialized. Changes after the editor has launched are ignored.
|
|
|
|
xref:init[`+init+`]:: Additional options passed to {productname} when it is initialized.
|
|
|
|
xref:plugins[`+plugins+`]:: Specify the editor plugins. This will be _combined_ with `+plugins+` in the `+init+` prop.
|
|
|
|
xref:toolbar[`+toolbar+`]:: Specify the editor toolbar. This will *override* the `+toolbar+` in the `+init+` prop.
|
|
|
|
[[managing-the-editor]]
|
|
=== Managing the editor
|
|
|
|
These props can be updated after the editor is initialized. Note that there are xref:event-binding[other events] not mentioned here.
|
|
|
|
xref:disabled[`+disabled+`]:: Should the editor be in read-only mode.
|
|
|
|
xref:initialvalue[`+initialValue+`]:: The starting value of the editor. Changing this value after the editor has loaded will reset the editor (including the editor content).
|
|
|
|
xref:event-binding[`+onBeforeAddUndo+`]:: An event handler for notifying when the editor is about to create an undo level, and preventing it if required. This is important for controlled components that restrict the allowed values of the editor.
|
|
|
|
xref:oneditorchange[`+onEditorChange+`]:: An event handler for detecting editor changes. Useful when implementing {productname} as a controlled component.
|
|
|
|
xref:event-binding[`+onInit+`]:: An event handler for notifying when the editor has initialized. Useful for getting the initial value of the editor or obtaining a reference to the editor that can be used for a uncontrolled component.
|
|
|
|
xref:value[`+value+`]:: Sets and enforces the value of the editor. Only used for a controlled component.
|
|
|
|
xref:tabIndex[`+value+`]:: Sets the tabindex of the target element that the editor wraps.
|
|
|
|
[[available-props]]
|
|
== Available props
|
|
|
|
None of the configuration props are *required* for the {productname} React component; however, if the `+apiKey+` prop is not configured when loading from {cloudname}, a warning message will be shown in the editor. For guidance about which props to use, see: xref:configuring-the-editor[Configuring the editor].
|
|
|
|
[[apikey]]
|
|
=== `+apiKey+`
|
|
|
|
{cloudname} API key.
|
|
|
|
Required for deployments using the {cloudname} to provide the {productname} editor without the warning message "A valid API key is required to continue using TinyMCE. Please alert the admin to check the current API key. Click here to learn more".
|
|
|
|
include::partial$misc/get-an-api-key.adoc[]
|
|
|
|
*Type:* `+String+`
|
|
|
|
*Default value:* `+'no-api-key'+`
|
|
|
|
==== Example: using `+apiKey+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
apiKey='no-api-key'
|
|
/>
|
|
----
|
|
|
|
[[licenseKey]]
|
|
=== `+licenseKey+`
|
|
|
|
{cloudname} License key.
|
|
|
|
Use this when self-hosting {productname} instead of loading from {cloudname}. For more information, see: xref:license-key.adoc[License Key].
|
|
|
|
*Type:* `+String+`
|
|
|
|
*Default value:* `+undefined+`
|
|
|
|
*Possible values:* `undefined`, `'gpl'` or a valid {productname} license key
|
|
|
|
==== Example: using `+licenseKey+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
licenseKey='your-license-key'
|
|
/>
|
|
----
|
|
|
|
[[cloudchannel]]
|
|
=== `+cloudChannel+`
|
|
|
|
Changes the {productname} build used for the editor to either a specific version or a channel indicating a stability level.
|
|
|
|
*Type:* `+String+`
|
|
|
|
*Default value:* `'{productmajorversion}'`
|
|
|
|
*Possible values:* `'{productmajorversion}'`, `'{productmajorversion}-testing'`, `'{productmajorversion}-dev'`, `'{productminorversion}'`
|
|
|
|
Changes the {productname} build used for the editor to one of the following {cloudname} channels:
|
|
|
|
* `{productmajorversion}` (*Default*): The current enterprise release of {productname}.
|
|
* `{productmajorversion}-testing`: The current release candidate for the next enterprise release of {productname}.
|
|
* `{productmajorversion}-dev`: The nightly-build version of {productname}.
|
|
* A version number such as `{productminorversion}`: The specific enterprise release version of {productname}.
|
|
|
|
Such as:
|
|
|
|
[source,jsx,subs="attributes+"]
|
|
----
|
|
<Editor
|
|
apiKey='no-api-key'
|
|
cloudChannel='{productmajorversion}-dev'
|
|
init={{ /* your other settings */ }}
|
|
/>
|
|
----
|
|
|
|
For information {productname} development channels, see: xref:editor-plugin-version.adoc#{productmajorversion}-{productmajorversion}-testing-and-{productmajorversion}-dev-release-channels[Specifying the {productname} editor version deployed from Cloud - dev, testing, and stable releases].
|
|
|
|
[[disabled]]
|
|
=== `+disabled+`
|
|
|
|
The `+disabled+` prop can dynamically switch the editor between a "disabled" (read-only) mode (`+true+`) and the standard editable mode (`+false+`).
|
|
|
|
*Type:* `Boolean`
|
|
|
|
*Default value:* `+false+`
|
|
|
|
*Possible values:* `+true+`, `+false+`
|
|
|
|
==== Example: using `+disabled+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
disabled={true}
|
|
/>
|
|
----
|
|
|
|
[[id]]
|
|
=== `+id+`
|
|
|
|
An id for the editor. Used for retrieving the editor instance using the `+tinymce.get('ID')+` method.
|
|
|
|
*Type:* `+String+`
|
|
|
|
*Default value:* Automatically generated https://tools.ietf.org/html/rfc4122[UUID]
|
|
|
|
==== Example: using `+id+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
id='your-id'
|
|
/>
|
|
----
|
|
|
|
[[init]]
|
|
=== `+init+`
|
|
|
|
Additional settings passed to the `+tinymce.init({...})+` method used to initialize the editor.
|
|
|
|
For information on the {productname} `+tinymce.init({...})+` method, see: xref:basic-setup.adoc[Basic setup].
|
|
|
|
When using `+tinymce-react+`:
|
|
|
|
* The `+init+` prop does not require the `+selector+` or `+target+` options
|
|
* If the `+selector+`, `+target+`, `+readonly+`, or `+license_key+` options are set using the `+init+` prop, they will be _overridden_ by the integration.
|
|
|
|
*Type:* `+Object+`
|
|
|
|
*Default value:* `+{ }+`
|
|
|
|
==== Example: using `+init+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
init={{
|
|
plugins: 'lists link image paste help wordcount',
|
|
toolbar: 'undo redo | blocks | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | help'
|
|
}}
|
|
/>
|
|
----
|
|
|
|
[[initialvalue]]
|
|
=== `+initialValue+`
|
|
|
|
The initial HTML content of the editor. This will reset the editor undo state and the cursor position when changed.
|
|
|
|
This may be set either before the editor loads, or soon afterwards by an asynchronous process.
|
|
|
|
IMPORTANT: Ensure that this is *not* updated by `+onEditorChange+` or the editor will be unusable.
|
|
|
|
*Type:* `+String+`
|
|
|
|
*Default value:* `+''+`
|
|
|
|
==== Example: using static `+initialValue+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
initialValue='<p>Once upon a time...</p>'
|
|
/>
|
|
----
|
|
|
|
==== Example: using asynchronous `+initialValue+`
|
|
|
|
[source,jsx]
|
|
----
|
|
const [initialValue, setInitialValue] = useState(undefined);
|
|
useEffect(() => {
|
|
// a real application might do a fetch request here to get the content
|
|
setTimeout(() => setInitialValue('<p>Once upon a time...</p>'), 500);
|
|
}, []);
|
|
|
|
return (
|
|
<Editor
|
|
initialValue={initialValue}
|
|
/>
|
|
);
|
|
----
|
|
|
|
[[inline]]
|
|
=== `+inline+`
|
|
|
|
Used to set the editor to inline mode. Using `+<Editor inline={true} />+` is the same as setting `+{inline: true}+` in the {productname} `+tinymce.init({...})+` method.
|
|
|
|
For information on inline mode, see: xref:inline-editor-options.adoc#inline[User interface options - `+inline+`] and xref:use-tinymce-inline.adoc[Setup inline editing mode].
|
|
|
|
*Type:* `+Boolean+`
|
|
|
|
*Default value:* `+false+`
|
|
|
|
*Possible values:* `+true+`, `+false+`
|
|
|
|
==== Example: using `+inline+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
inline={true}
|
|
/>
|
|
----
|
|
|
|
[[oneditorchange]]
|
|
=== `+onEditorChange+`
|
|
|
|
Used to store the state of the editor outside the {productname} React component. This prop is commonly used when using the {productname} React component as a controlled component.
|
|
|
|
It is called with two arguments:
|
|
|
|
`+value+`:: The current value of the editor. This is HTML.
|
|
|
|
`+editor+`:: A reference to the editor.
|
|
|
|
For detailed information on using `+onEditorChange+`, see: xref:using-the-tinymce-react-component-as-a-controlled-component[Using the {productname} React component as a controlled component].
|
|
|
|
*Type:* `+EventHandler+`
|
|
|
|
[[outputformat]]
|
|
=== [.line-through]#`+outputFormat+`# (__removed__)
|
|
|
|
IMPORTANT: This option was removed with the release of the {productname} React component 4.0.0.
|
|
|
|
This option was used to specify the format of the content produced by the
|
|
xref:oneditorchange[`+onEditorChange+`] event, however as it did not change the
|
|
input format it was almost impossible to use correctly.
|
|
|
|
==== Example: replacing usage of `+outputFormat+`
|
|
|
|
[source,jsx]
|
|
----
|
|
const [value, setValue] = useState('<p>The quick brown fox jumps over the lazy dog</p>');
|
|
const [text, setText] = useState('');
|
|
|
|
return (
|
|
<>
|
|
<Editor
|
|
value={value}
|
|
onInit={(evt, editor) => {
|
|
setText(editor.getContent({format: 'text'}));
|
|
}}
|
|
onEditorChange={(newValue, editor) => {
|
|
setValue(newValue);
|
|
setText(editor.getContent({format: 'text'}));
|
|
}}
|
|
/>
|
|
<pre>{text}</pre>
|
|
</>
|
|
);
|
|
----
|
|
|
|
[[plugins]]
|
|
=== `+plugins+`
|
|
|
|
Used to include plugins for the editor. Using `+<Editor plugins='lists' />+` is the same as setting `+{plugins: 'lists'}+` in the {productname} `+tinymce.init({...})+` method.
|
|
|
|
For information on adding plugins to {productname}, see: xref:work-with-plugins.adoc[Add plugins to {productname}].
|
|
|
|
*Type:* `+String+` or `+Array+`
|
|
|
|
==== Example: using `+plugins+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
plugins='lists code'
|
|
/>
|
|
----
|
|
|
|
[[rollback]]
|
|
=== `+rollback+`
|
|
|
|
Used to configure the rollback timer. This is the milliseconds between an event
|
|
being emitted by the xref:oneditorchange[`+onEditorChange+`] prop and the
|
|
xref:value[`+value+`] prop being enforced.
|
|
|
|
When `+rollback+` is `false` the xref:value[`+value+`] prop will not be
|
|
enforced unless it changes.
|
|
|
|
*Type:* `+Number+` or `false`
|
|
|
|
*Default value:* `200`
|
|
|
|
==== Example: using `+rollback+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
rollback={0}
|
|
value="<p>This value will be restored almost as soon as it is changed.</p>"
|
|
/>
|
|
----
|
|
|
|
[[scriptloading]]
|
|
=== `+scriptLoading+`
|
|
|
|
Used to configure the script tag created to load {productname}.
|
|
|
|
*Type:* `+Object+`
|
|
[source,ts]
|
|
----
|
|
type ScriptLoading = {
|
|
async?: boolean;
|
|
defer?: boolean;
|
|
delay?: number;
|
|
};
|
|
----
|
|
|
|
Contains 3 settings:
|
|
|
|
`+async+`:: Sets the https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-async[`+async+`] attribute on the script tag created to load {productname}.
|
|
+
|
|
[quote, https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-async]
|
|
For classic scripts, if the async attribute is present, then the classic script will be fetched in parallel to parsing and evaluated as soon as it is available.
|
|
+
|
|
*Type:* `+Boolean+`
|
|
+
|
|
*Default value:* `false`
|
|
|
|
`+defer+`:: Sets the https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer[`+defer+`] attribute on the script tag created to load {productname}.
|
|
+
|
|
[quote, https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer]
|
|
This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed, but before firing DOMContentLoaded.
|
|
+
|
|
*Type:* `+Boolean+`
|
|
+
|
|
*Default value:* `false`
|
|
|
|
`+delay+`:: The script tag to load {productname} will be added after the specified delay in milliseconds.
|
|
+
|
|
*Type:* `+Number+`
|
|
+
|
|
*Default value:* `0`
|
|
|
|
|
|
[[example-loading-siteproductname-asynchronously]]
|
|
==== Example: loading {productname} asynchronously
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor scriptLoading={{ async: true }}>
|
|
----
|
|
|
|
[[example-delaying-load-of-siteproductname-for-500-milliseconds]]
|
|
==== Example: delaying load of {productname} for 500 milliseconds
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor scriptLoading={{ delay: 500 }}>
|
|
----
|
|
|
|
[[tagname]]
|
|
=== `+tagName+`
|
|
|
|
Only valid when xref:inline[`+<Editor inline={true} />+`]. Used to define the HTML element for the editor in inline mode.
|
|
|
|
*Type:* `+String+`
|
|
|
|
*Default value:* `+'div'+`
|
|
|
|
==== Example: using `+tagName+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
inline={true}
|
|
tagName='section'
|
|
/>
|
|
----
|
|
|
|
[[textareaname]]
|
|
=== `+textareaName+`
|
|
|
|
Only valid when the editor is in classic (iframe) mode. Sets the `+name+` attribute for the `+textarea+` element used for the editor in forms.
|
|
|
|
*Type:* `+String+`
|
|
|
|
==== Example: using `+textareaName+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<form method="post">
|
|
<Editor
|
|
textareaName='description'
|
|
/>
|
|
<button type="submit">Submit</button>
|
|
</form>
|
|
----
|
|
|
|
[[toolbar]]
|
|
=== `+toolbar+`
|
|
|
|
Used to set the toolbar for the editor. Using `+<Editor toolbar='bold' />+` is the same as setting `+{toolbar: 'bold'}+` in the {productname} method `+tinymce.init({...})+`.
|
|
|
|
For information setting the toolbar for {productname}, see: xref:toolbar-configuration-options.adoc#toolbar[User interface options - toolbar].
|
|
|
|
*Type:* `+String+`
|
|
|
|
*Possible values:* See xref:available-toolbar-buttons.adoc[Toolbar Buttons Available for {productname}].
|
|
|
|
==== Example: using `+toolbar+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
plugins='code'
|
|
toolbar='bold italic underline code'
|
|
/>
|
|
----
|
|
|
|
[[tinymcescriptsrc]]
|
|
=== `+tinymceScriptSrc+`
|
|
|
|
Use the `+tinymceScriptSrc+` prop to specify an external version of {productname} to lazy load.
|
|
|
|
*Type:* `+String+`
|
|
|
|
==== Example: using `+tinymceScriptSrc+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
tinymceScriptSrc='/path/to/tinymce.min.js'
|
|
/>
|
|
----
|
|
|
|
[[value]]
|
|
=== `+value+`
|
|
|
|
Sets the HTML content of the editor when operating as a controlled component.
|
|
|
|
When this prop is different to the current editor content, the editor content will be changed to match (within 200 milliseconds) and an undo level will be created. When the editor content changes by this mechanism, the editor will attempt to retain the selection, however if the previous selection does not exist in the new content, the cursor returns to the start of the document.
|
|
|
|
This prop allows the editor to be used as a controlled component by setting the `+value+` prop and using the `+onEditorChange+` event to update the `+value+`.
|
|
|
|
For detailed information on using the `+value+` prop, see: xref:using-the-tinymce-react-component-as-a-controlled-component[Using the {productname} React component as a controlled component].
|
|
|
|
*Type:* `+String+`
|
|
|
|
[[tabIndex]]
|
|
=== `+tabIndex+`
|
|
|
|
Use the `+tabIndex+` prop to set the https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex[tabindex] on the target element that the editor wraps.
|
|
|
|
*Type:* `+Number+`
|
|
|
|
==== Example: using `+tabIndex+`
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor
|
|
tabIndex={-1}
|
|
/>
|
|
----
|
|
|
|
[[using-the-tinymce-react-component-as-a-uncontrolled-component]]
|
|
== Using the {productname} React component as a uncontrolled component
|
|
|
|
The {productname} React component is designed to be used as an uncontrolled component, which allows the editor to perform well on larger documents.
|
|
|
|
When using the editor as an uncontrolled component, avoid using the `+value+` and `+onEditorChange+` props. {companyname} recommends retrieving the editor content when it is needed. The `+onInit+` event handler can be used to store a editor reference when the editor is loaded to assist with retrieving the content.
|
|
|
|
To provide visual feedback to the user when the content is ready to be saved, use the `+onDirty+` event handler; combined with clearing the editor's "dirty" state when saving the editor content.
|
|
|
|
include::partial$misc/concept-dirty-state.adoc[]
|
|
|
|
=== Example: functional uncontrolled component with save button and dirty state
|
|
|
|
[source,jsx]
|
|
----
|
|
function MyComponent({initialValue}) {
|
|
const editorRef = useRef(null);
|
|
const [dirty, setDirty] = useState(false);
|
|
useEffect(() => setDirty(false), [initialValue]);
|
|
const save = () => {
|
|
if (editorRef.current) {
|
|
const content = editorRef.current.getContent();
|
|
setDirty(false);
|
|
editorRef.current.setDirty(false);
|
|
// an application would save the editor content to the server here
|
|
console.log(content);
|
|
}
|
|
};
|
|
return (
|
|
<>
|
|
<Editor
|
|
initialValue={initialValue}
|
|
onInit={(evt, editor) => editorRef.current = editor}
|
|
onDirty={() => setDirty(true)}
|
|
/>
|
|
<button onClick={save} disabled={!dirty}>Save</button>
|
|
{dirty && <p>You have unsaved content!</p>}
|
|
</>
|
|
);
|
|
}
|
|
----
|
|
|
|
[[using-the-tinymce-react-component-as-a-controlled-component]]
|
|
== Using the {productname} React component as a controlled component
|
|
|
|
CAUTION: The controlled component can have performance problems on large documents as it requires converting the entire document to a string on each keystroke or modification.
|
|
|
|
To use the editor as a https://legacy.reactjs.org/docs/forms.html#controlled-components[controlled component], both the `+value+` and `+onEditorChange+` props are required.
|
|
|
|
The `+value+` prop is used to set and re-set the editor content. If it is not updated to the latest version of the editor content, the editor will rollback any changes.
|
|
|
|
The `+onEditorChange+` prop is used to provide an event handler that will be run when any change is made to the editor content. Changes to the editor must be applied to the `+value+` prop within _200 milliseconds_ to prevent the changes being rolled back.
|
|
|
|
=== Example: functional controlled component
|
|
|
|
[source,jsx]
|
|
----
|
|
function MyComponent({initialValue}) {
|
|
const [value, setValue] = useState(initialValue ?? '');
|
|
useEffect(() => setValue(initialValue ?? ''), [initialValue]);
|
|
return (
|
|
<Editor
|
|
initialValue={initialValue}
|
|
value={value}
|
|
onEditorChange={(newValue, editor) => setValue(newValue)}
|
|
/>
|
|
);
|
|
}
|
|
----
|
|
|
|
=== Example: class controlled component
|
|
|
|
[source,jsx]
|
|
----
|
|
class MyComponent extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.state = { value: props.initialValue ?? '' };
|
|
this.handleEditorChange = this.handleEditorChange.bind(this);
|
|
}
|
|
|
|
componentDidUpdate(prevProps) {
|
|
if (this.props.initialValue !== prevProps.initialValue) {
|
|
this.setState({ value: this.props.initialValue ?? '' })
|
|
}
|
|
}
|
|
|
|
handleEditorChange(value, editor) {
|
|
this.setState({ value });
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<Editor
|
|
initialValue={this.props.initialValue}
|
|
value={this.state.value}
|
|
onEditorChange={this.handleEditorChange}
|
|
/>
|
|
)
|
|
}
|
|
}
|
|
----
|
|
|
|
When the editor must be restricted to avoid invalid states, such as exceeding a maximum length, then a handler for `+onBeforeAddUndo+` must be added to avoid those states in the undo history.
|
|
|
|
=== Example: limited length controlled component
|
|
|
|
[source,jsx]
|
|
----
|
|
function MyComponent({initialValue, limit}) {
|
|
const sizeLimit = limit ?? 50;
|
|
const [ value, setValue ] = React.useState(initialValue ?? '');
|
|
const [ length, setLength ] = React.useState(0);
|
|
|
|
const handleInit = (evt, editor) => {
|
|
setLength(editor.getContent({ format: 'text' }).length);
|
|
};
|
|
|
|
const handleUpdate = (value, editor) => {
|
|
const length = editor.getContent({ format: 'text' }).length;
|
|
if (length <= sizeLimit) {
|
|
setValue(value);
|
|
setLength(length);
|
|
}
|
|
};
|
|
|
|
const handleBeforeAddUndo = (evt, editor) => {
|
|
const length = editor.getContent({ format: 'text' }).length;
|
|
// note that this is the opposite test as in handleUpdate
|
|
// because we are determining when to deny adding an undo level
|
|
if (length > sizeLimit) {
|
|
evt.preventDefault();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Editor
|
|
initialValue={initialValue}
|
|
value={value}
|
|
onInit={handleInit}
|
|
onEditorChange={handleUpdate}
|
|
onBeforeAddUndo={handleBeforeAddUndo}
|
|
/>
|
|
<p>Remaining: {sizeLimit - length}</p>
|
|
</>
|
|
);
|
|
};
|
|
----
|
|
|
|
For information on controlled components in React, see: https://legacy.reactjs.org/docs/forms.html#controlled-components[React Docs - Controlled Components].
|
|
|
|
[[event-binding]]
|
|
== Event binding
|
|
|
|
Functions can be bound to editor events, such as:
|
|
|
|
[source,jsx]
|
|
----
|
|
<Editor onSelectionChange={this.handlerFunction} />
|
|
----
|
|
|
|
When the handler is called (*handlerFunction* in this example), it is called with two arguments:
|
|
|
|
`+event+`:: The {productname} event object.
|
|
|
|
`+editor+`:: A reference to the editor.
|
|
|
|
The following events are available:
|
|
|
|
* `+onActivate+`
|
|
* `+onAddUndo+`
|
|
* `+onBeforeAddUndo+`
|
|
* `+onBeforeExecCommand+`
|
|
* `+onBeforeGetContent+`
|
|
* `+onBeforeRenderUI+`
|
|
* `+onBeforeSetContent+`
|
|
* `+onBeforePaste+`
|
|
* `+onBlur+`
|
|
* `+onChange+`
|
|
* `+onClearUndos+`
|
|
* `+onClick+`
|
|
* `+onContextMenu+`
|
|
* `+onCompositionEnd+`
|
|
* `+onCompositionStart+`
|
|
* `+onCompositionUpdate+`
|
|
* `+onCopy+`
|
|
* `+onCut+`
|
|
* `+onDblclick+`
|
|
* `+onDeactivate+`
|
|
* `+onDirty+`
|
|
* `+onDrag+`
|
|
* `+onDragDrop+`
|
|
* `+onDragEnd+`
|
|
* `+onDragGesture+`
|
|
* `+onDragOver+`
|
|
* `+onDrop+`
|
|
* `+onExecCommand+`
|
|
* `+onFocus+`
|
|
* `+onFocusIn+`
|
|
* `+onFocusOut+`
|
|
* `+onGetContent+`
|
|
* `+onHide+`
|
|
* `+onInit+`
|
|
* `+onInput+`
|
|
* `+onKeyDown+`
|
|
* `+onKeyPress+`
|
|
* `+onKeyUp+`
|
|
* `+onLoadContent+`
|
|
* `+onMouseDown+`
|
|
* `+onMouseEnter+`
|
|
* `+onMouseLeave+`
|
|
* `+onMouseMove+`
|
|
* `+onMouseOut+`
|
|
* `+onMouseOver+`
|
|
* `+onMouseUp+`
|
|
* `+onNodeChange+`
|
|
* `+onObjectResizeStart+`
|
|
* `+onObjectResized+`
|
|
* `+onObjectSelected+`
|
|
* `+onPaste+`
|
|
* `+onPostProcess+`
|
|
* `+onPostRender+`
|
|
* `+onPreProcess+`
|
|
* `+onProgressState+`
|
|
* `+onRedo+`
|
|
* `+onRemove+`
|
|
* `+onReset+`
|
|
* `+onSaveContent+`
|
|
* `+onSelectionChange+`
|
|
* `+onSetAttrib+`
|
|
* `+onSetContent+`
|
|
* `+onShow+`
|
|
* `+onSubmit+`
|
|
* `+onUndo+`
|
|
* `+onVisualAid+`
|