I'm using CKEDITOR5 with React and I have succeed to implement CKEDITOR in my project but when I go on my view I can only see the toolbar.
The content area is invisible until I click on it and the blue border appear.
If I remove my focus on it there is no border anymore.
Here is my code
import React, { Component } from 'react'
import CKEditor from '#ckeditor/ckeditor5-react';
import DecoupledEditor from '#ckeditor/ckeditor5-build-decoupled-document';
export default class BlogNew extends Component {
render() {
return (
<div>
<CKEditor
editor={ DecoupledEditor }
onInit={ editor => {
editor.ui.getEditableElement().parentElement.insertBefore(
editor.ui.view.toolbar.element,
editor.ui.getEditableElement()
);
} }
onChange={(event, editor) => {
const data = editor.getData();
this.setState({ text: data })
}}
/>
</div>
)}
DecoupledEditor is dedicated to integrations which require a customized UI.
Make sure to add the style to your component:
:root {
.ck.ck-editor__editable_inline {
border: 1px solid var(--ck-color-base-border);
}
}
see # ckeditor5-ui
Related
I'm building an application to save locations i.e countries cities regions etc. When clicking on my on click function the states of two div tags change changing the class name and making one invisible and one visible. advice?
import React, { useState }from "react";
import Area from "../ReadFolder/geographicMainComponents/areaMainComponent.jsx";
import City from "../ReadFolder/geographicMainComponents/cityMainComponent.jsx";
import Country from "../ReadFolder/geographicMainComponents/countryMainComponent.jsx";
import Neighborhood from "../ReadFolder/geographicMainComponents/neighborhoodMainComponent.jsx";
import Region from "../ReadFolder/geographicMainComponents/regionMainComponent.jsx";
import { default as AreaW} from "../WriteFolder/geographicMainComponents/areaMainComponent.jsx";
import { default as CityW} from "../WriteFolder/geographicMainComponents/cityMainComponent.jsx";
import { default as CountryW} from "../WriteFolder/geographicMainComponents/countryMainComponent.jsx";
import { default as NeighborhoodW} from "../WriteFolder/geographicMainComponents/neighborhoodMainComponent.jsx";
import { default as RegionW} from "../WriteFolder/geographicMainComponents/regionMainComponent.jsx";
export default function MenuWrapper({type,id,isEdit}){
let [edit,setEdit] = useState(isEdit);
let changer=()=>{console.log('you clicked me!');setEdit(!setEdit)}
if(type==='country'){
return(
<div key={"frommenulist"+id}>
<div className={edit ? 'd-block' :'d-none'}><CountryW id={id}/><button onClick={changer}>read</button></div>
<div className={edit ? 'd-none' : 'd-block'}><Country id={id} /><button onClick={changer}>edit</button></div>
</div>
);
}
}
It's difficult to work out what clicking those buttons is meant to do. It looks like you need only one div/button block, and clicking the edit button determines what happens (ie to make the country editable somehow).
At the moment it looks like you want to set the display to either block/none but you can't set an element's display to none and still expect to be able to click the button to reset the display because there will be no button to click on. Further: unless the type is "country" the component doesn't return anything so you need a condition in there to return something if type isn't "country" (or add a condition in the parent component to prevent the component rendering at all if that condition is met).
Here's a small example that uses local state to manage whether the div is a plain one or an editable one. Click the edit button, and then click in the div to be able to edit it. You can then click the read button to switch off contentEditable and keep the content.
const { useState } = React;
function MenuWrapper({ type, id }) {
const [ edit, setEdit ] = useState(false);
function handleClick() {
setEdit(!edit);
}
// Return a default div if type is not "country"
if (type !== 'country') return <div>Not country</div>
const divStyle = [
'country',
edit && 'edit'
].join(' ');
return (
<div>
<div>
<div
className={divStyle}
contentEditable={edit}
>Country Id: {id}
</div>
<button onClick={handleClick}>
{edit ? 'Read' : 'Edit'}
</button>
</div>
</div>
);
}
ReactDOM.render(
<MenuWrapper type="country" id="1" />,
document.getElementById('react')
);
.country { padding: 0.25em; }
.edit { border: 1px solid green; }
button { margin-top: 1em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
I'm using the following JSX code with a custom CKEditor that I built using the online-builder When I add this editor to my node modules and try to use it like the following:
import React, { Component } from 'react';
//import Editor from 'ckeditor5-custom-build/build/ckeditor';
import ClassicEditor from '#ckeditor/ckeditor5-build-custom';
import { CKEditor } from '#ckeditor/ckeditor5-react'
const editorConfiguration = {
toolbar: [ 'heading', '|', 'bold', 'italic', 'underline', 'strikethrough', '|' ]
};
class App extends Component {
render() {
return (
<div className="App">
<h2>Using CKEditor 5 from online builder in React</h2>
<CKEditor
editor={ ClassicEditor }
config={ editorConfiguration }
data="<p>Hello from CKEditor 5!</p>"
onReady={ editor => {
// You can store the "editor" and use when it is needed.
console.log( 'Editor is ready to use!', editor );
} }
onChange={ ( event, editor ) => {
const data = editor.getData();
console.log( { event, editor, data } );
} }
onBlur={ ( event, editor ) => {
console.log( 'Blur.', editor );
} }
onFocus={ ( event, editor ) => {
console.log( 'Focus.', editor );
} }
/>
</div>
);
}
}
export default App;
I get an error stating that TypeError: this.props.editor.create is not a function. Is there some step that I am apparently missing? The help is much appreciated.
After hours of research online and trying to figure out where the custom build went wrong it turned out to be the most simple solution ever! In my custom build's src folder where the ckeditor.js file is located (containing the custom build before being built) I noticed at the bottom of the file it looked something like this export default { Editor, Watchdog }; Seeing this I immediately knew the solution was to import the custom editor as a named import. If you import it as a default import then you will not have any of the features of the editor but rather the entire export as shown above. Simple solution change the line that says import ClassicEditor from '#ckeditor/ckeditor5-build-custom'; to import {Editor as ClassicEditor} from '#ckeditor/ckeditor5-build-custom'; and now it will import the way it was meant to be imported.The interesting part about this, is that if you do not add Watchdog to your custom build (using the online-builder) then it should be imported as a default import as it will export as follows export default Editor;
I am using CKEditor5 React Component Framework.I have successfully integrated the CKEditor in my project.And Being Able to use it.
But the problem is that I have to save the Content of the editor to the database and then display it to website.. All I get in the content
<blockquote><p>Hello from CKEditor 5!</p></blockquote>
And While Displaying it does not applies the css of CkEditor to show ..
Setup for CKEDITOR IS
import React, { Component } from 'react';
import CKEditor from '#ckeditor/ckeditor5-react';
import Classiceditor from '#ckeditor/ckeditor5-build-classic';
export class ClassicEditor extends Component {
constructor(){
super();
this.state = {
content : ""
}
}
onCashange = data => {
console.log( "Called" );
this.setState({
content : data.getData()
})
}
render() {
Classiceditor.builtinPlugins.map( plugin => console.log(plugin.pluginName) );
console.log("State", this.state.content);
return (
<>
<div className='App'>
<h2> Using CKEditor</h2>
<CKEditor
editor = { Classiceditor }
data = "<p>Hello from CKEditor 5!</p>"
onInit = { editor => {
//console.log( 'Editor is ready to use!', editor )
} }
onChange = { ( event, editor ) => {
this.onCashange( editor );
// const data = editor.getData();
// this.onChange( data );
// //console.log( { event, editor, data } );
}}
onBlur = { editor =>
console.log("Blur", editor) }
onFocus = { editor => {
//console.log( "Focus", editor )
} }
/>
</div>
<div className='editor'>
{ this.state.content }
</div>
</>
)
}
}
export default ClassicEditor
There are 2 options:
Download or using script to get Full CSS and include it in your project.
Link here
Note: You have to add a parent container with a class name ck-content
Create a custom CKEditor 5 build from the source code with all the CSS (both UI and the content) extracted to a separate file
Advance Guide
You can see more here from the documentation:
Content Styles
React does not allow you to render html code directly. Instead you have to use dangerouslySetInnerHTML attribute to do so. Do the following to solve your problem,
<div dangerouslySetInnerHTML={this.createMarkup()} className='editor'></div>
and have a method on the class as
createMarkup = () => {
return { __html: this.state.content };
}
This will make sure that you are not rendering the raw HTML to the page.
You can read more about this here
you can just install npm package like npm i react-render-html
enter link description here
and use it like :
<div className='...'>
{renderHTML(someHTML)}
</div>
Here is an answer to above question:
<div style={{wordWrap:'break-word',display:'inline-block'}}>
<div className="editor" dangerouslySetInnerHTML={{_html:this.state.content}}/>
</div>
The code is as follows.
import CKEditor from '#ckeditor/ckeditor5-react';
import ClassicEditor from '#ckeditor/ckeditor5-build-classic';
render() {
let selectedDocument = this.state.documentDetails;
return (
<div>
<div>
{
selectedDocument.html_content &&
<div className="form-group">
<CKEditor
editor={ ClassicEditor }
data={selectedDocument.html_content }
onInit={ editor => {
} }
onChange={ ( event, editor ) => {
const data = editor.getData();
let obj = {
target: {
name: 'html_content',
value: data
}
}
this.handleChange(obj);
} }
/>
</div>
}
</div>
</div>
);
}
Using the above code, the editor is displayed with basic toolbar buttons.
Now I need to add a new button to the toolbar which when clicked a javascript function needs to be called.
I have seen documentation on creating custom plugins, but I am not sure on how to implement this in the react way.
Any ideas on how to implement this? A sample piece of code would e really helpful.
Find config.js in CKEditor folder and update config.extraPlugins with your plugin like config.extraPlugins = 'html5video,widget,widgetselection,clipboard,lineutils,videoembed';
It will display new toolbar or button on CKEditor.
I'm using ReactJs and react-fa to access Font Awesome icons. I need to put one of the icons inside a text input dynamically.
Here is my code:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Icon } from 'react-fa';
import '../index.css';
class SearchInput extends Component {
static propTypes = {
onKeyUp: PropTypes.object,
placeholder: PropTypes.placeholder,
iconName: PropTypes.string
};
handleKeyUp = (content) => {
console.log(content);
}
render() {
let icon = <Icon name={this.props.iconName} />;
let extra = {
backgroundImage: icon
}
return (
<input className='ux-search-input' style={extra} type='text' onKeyUp={this.handleKeyUp} placeholder={this.props.placeholder} />
);
}
};
export default SearchInput;
This does not work - no icons at all. Repair that in that case I have no URLs to match, as the icon variable will be a ReactJs component.
react-fa is a React component, and it renders as html like <i class="fa fa-name" />, so you can't use it as a style. You should use something like this:
return (
<span>
{ icon }
<input className='ux-search-input' style={extra} type='text' onKeyUp={this.handleKeyUp} placeholder={this.props.placeholder} />
</span>
);
and add some styling to match proper icon position.
Instead of using React component, try using a regular icon tag in front of the input field, and then use css to move the icon to the appropriate position.
For example:
JSX:
<i class={this.props.iconName} id="icon" />
CSS:
#icon {
// Adjust margins and position to fit the input background
margin-left: 30px;
}