Reputation: 550
First thing first, I'm trying to implement tinyMCE to a component from react-bootstrap.
Said component is 'dynamic'. It can be any type of input I desire but when I try to use it as a textarea with tinyMCE, the state does not return any data from said input and my DB updates fail(learned it the hard way).
The first component I'm using it with is called the Edit.js. This input should store the new values on producerData which it does but only when I dont initialize the tinyMCE.
const handleChange = (name) => (e) => {
setIsBlocking(e.target.value.length > 0)
setProducerData({ ...producerData, [name]: e.target.value })
};
<FormInput
id={`text`}
name={`text`}
asType={`textarea`}
handleChange={handleChange('text')}
value={text}
plugins={`toolbar`}
/>
With that being said, here it is the FormInput component. I previously mentioned that it works but no necessarily with tinyMCE(that's the reason I currently have it commented) which is what I need:
import React from 'react'
// HELPERS
import { useScript } from '../../helpers/utilities'
// TINYMCE
import Form from 'react-bootstrap/Form'
const FormInput = ({
id = ``,
name = ``,
type = ``,
asType = ``,
placeholder = `Write here...`,
value = ``,
handleChange,
plugins = ``,
classStr = ``,
required = false,
disabled = false,
ariaLabel = ``,
ariaDescribedby = ``,
autoComplete = ``,
children,
}) => {
// useScript(
// 'tinyMCE',
// `https://cdnjs.cloudflare.com/ajax/libs/tinymce/5.6.2/tinymce.min.js`,
// 'origin',
// 'head',
// false
// );
// if (asType === `textarea`) {
// window?.tinymce?.init({
// selector: `textarea#${id}`,
// // skin: `bootstrap`,
// branding: false,
// height: 300,
// plugins: `toc pagebreak charmap textpattern imagetools ${plugins}`,
// });
// }
return (
<Form.Control
{...{
...(id && { id: id }),
...(name && { name: name }),
...(type && { type: type }),
...(asType && { as: asType }),
...(placeholder && { placeholder: placeholder }),
...(handleChange && { onChange: handleChange }),
...(value && { value: value }),
...(classStr && { className: classStr }),
...(required && { required: required }),
...(disabled && { disabled: disabled }),
...(ariaLabel && `aria-label=${ariaLabel}`),
...(ariaDescribedby && `aria-describedby=${ariaDescribedby}`),
...(autoComplete && { autoComplete: autoComplete }),
}}
>
{children && children}
</Form.Control>
)
}
export default FormInput
Again, if I did not explain myself well: The code above works by itself but I want it to work with TinyMCE
Has anyone here used react-bootstrap and tinyMCE? Thanks!.
Upvotes: 2
Views: 1124
Reputation: 550
In the end this is what I ended up with:
import React from 'react';
import 'tinymce/tinymce';
import 'tinymce/icons/default';
import 'tinymce/themes/silver';
import 'tinymce/plugins/paste';
import 'tinymce/plugins/link';
import 'tinymce/plugins/image';
import 'tinymce/plugins/table';
import 'tinymce/skins/ui/oxide/skin.min.css';
import 'tinymce/skins/ui/oxide/content.min.css';
import 'tinymce/skins/content/default/content.min.css';
import { Editor } from '@tinymce/tinymce-react';
import ReactHtmlParser from 'react-html-parser';
// HELPERS
import { useScript } from '../../helpers/utilities';
const FormInput = ({
id = ``,
name = ``,
value = ``,
handleChange,
plugins = ``,
isRequired = false
}) => {
useScript(
'tinyMCE',
`https://cdnjs.cloudflare.com/ajax/libs/tinymce/5.6.2/tinymce.min.js`,
'origin',
'head',
false
);
const parseEditorData = (content, editor) => {
//content is the current value of the text editor
// editor is an object that holds the html element that in this case is the text area where the name prop will be stored.
const { targetElm } = editor;
// This name value references the prop that you pass as textAreaName (content in your case)
const { name } = targetElm;
// This function returns an object that your handle change can parse correctly
return {
target: {
name,
value: content
}
};
};
return (
<Editor
apiKey={process.env.TINIYMCE_APIKEY}
textareaName={name}
initialValue={`${ReactHtmlParser(value)}`}
init={{
selector: `textarea#${id}`,
skin: `bootstrap`,
branding: false,
height: 300,
plugins: `image link advcode media powerpaste codesample preview wordcount visualchars toc pagebreak charmap textpattern imagetools ${plugins}`,
autoresize_bottom_margin: 50,
textpattern_patterns: [
{ start: '*', end: '*', format: 'italic' },
{ start: '**', end: '**', format: 'bold' },
{ start: '#', format: 'h1' },
{ start: '##', format: 'h2' },
{ start: '###', format: 'h3' },
{ start: '####', format: 'h4' },
{ start: '#####', format: 'h5' },
{ start: '######', format: 'h6' },
{ start: '1. ', cmd: 'InsertOrderedList' },
{ start: '* ', cmd: 'InsertUnorderedList' },
{ start: '- ', cmd: 'InsertUnorderedList' }
]
}}
onChange={(content, editor) =>
handleChange(parseEditorData(content.level.content, editor))
}
outputFormat={`text`}
required={isRequired}
/>
);
};
export default FormInput;
Usage:
import TinyMCE from '../../../layout/TinyMCE';
<TinyMCE
id={`text`}
name={`text`}
handleChange={handleChange('text')}
value={text}
plugins={`toolbar`}
isRequired={true}
/>
Upvotes: 1