draftjs, как запустить редактор с контентом
Наткнулся на этот классный текстовый редактор, draft.js от фейсбука. Я пытаюсь следовать примеру в github, но я хочу создать редактор с содержимым вместо пустого редактора.
var EditorState = Draft.EditorState;
var RichEditor = React.createClass({
getInitialState(){
return {editorState: EditorState.createWithContent("Hello")}
//the example use this code to createEmpty editor
// return ({editorState: EditorState.createEmpty()})
}
});
запустить его, но я получаю сообщение об ошибке, говорящее, что "Uncaught TypeError: contentState.getBlockMap не является функцией"
10 ответов
Первый аргумент EditorState.createWithContent - это ContentState
, а не строка. Вам необходимо импортировать ContentState
var EditorState = Draft.EditorState;
var ContentState = Draft.ContentState;
Используйте ContentState.createFromText и передайте результат в EditorState.createWithContent.
return {
editorState: EditorState.createWithContent(ContentState.createFromText('Hello'))
};
Я создал набор пакетов для DraftJS, чтобы помочь с импортом и экспортом контента (HTML/Markdown). Я использую их в своем проекте " Реакция на будущее". Вероятно, вы ищете: draft-js-import-html на npm.
npm install draft-js-import-html
Пример того, как вы можете использовать это:
var stateFromHTML = require('draft-js-import-html').stateFromHTML;
var EditorState = Draft.EditorState;
var RichEditor = React.createClass({
getInitialState() {
let contentState = stateFromHTML('<p>Hello</p>');
return {
editorState: EditorState.createWithContent(contentState)
};
}
});
Модули, которые я опубликовал:
Произошли некоторые изменения API, для ясности в этих примерах используется последний API, который является v0.10.0.
Есть много способов, но в основном у вас есть три варианта, в зависимости от того, хотите ли вы использовать простой текст, стилизованный текст или HTML-разметку для ресурса контента.
Какой простой текст очевиден, но для стилизованного текста вам нужно использовать либо сериализованный объект javasript, либо html-разметку.
Давайте начнем с простого текста:
import {Editor, EditorState} from 'draft-js';
class MyEditor extends Component{
constructor(props) {
super(props);
const plainText = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.';
const content = ContentState.createFromText(plainText);
this.state = { editorState: EditorState.createWithContent(content)};
this.onChange = (editorState) => {
this.setState({editorState});
}
}
render(){
return(
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
/>
)
}
}
Для импорта стилизованного контента в Draft.js предусмотрены служебные функции convertFromRaw и convertFromHTML.
Функция convertFromRaw принимает необработанный объект JavaScript в качестве параметра. Здесь мы используем JSON-объект JSON в качестве источника контента:
class MyEditor extends Component{
constructor(props) {
super(props);
const rawJsText = `{
"entityMap": {},
"blocks": [
{
"key": "e4brl",
"text": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
"type": "unstyled",
"depth": 0,
"inlineStyleRanges": [
{
"offset": 0,
"length": 11,
"style": "BOLD"
},
{
"offset": 28,
"length": 29,
"style": "BOLD"
},
{
"offset": 12,
"length": 15,
"style": "ITALIC"
},
{
"offset": 28,
"length": 28,
"style": "ITALIC"
}
],
"entityRanges": [],
"data": {}
},
{
"key": "3bflg",
"text": "Aenean commodo ligula eget dolor.",
"type": "unstyled",
"depth": 0,
"inlineStyleRanges": [],
"entityRanges": [],
"data": {}
}
]
}`;
const content = convertFromRaw(JSON.parse(rawJsText));
this.state = { editorState: EditorState.createWithContent(content)};
this.onChange = (editorState) => {
this.setState({editorState});
}
}
render(){
return(
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
/>
)
}
}
Draft.js предоставляет функцию convertToRaw, так что вы можете преобразовать состояние вашего редактора в необработанный объект javascript для длительного хранения.
И, наконец, вот как вы делаете это с HTML-разметкой:
class MyEditor extends Component{
constructor(props) {
super(props);
const html = `<p>Lorem ipsum <b>dolor</b> sit amet, <i>consectetuer adipiscing elit.</i></p>
<p>Aenean commodo ligula eget dolor. <b><i>Aenean massa.</i></b></p>`;
const blocksFromHTML = convertFromHTML(html);
const content = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
this.state = { editorState: EditorState.createWithContent(content)};
this.onChange = (editorState) => {
this.setState({editorState});
}
}
render(){
return(
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
/>
)
}
}
Ты можешь использовать convertFromHTML
импортировать HTML с createWithContent
import { convertFromHTML, ContentState } from 'draft-js'
const html = '<div><p>hello</p></div>'
const blocksFromHTML = convertFromHTML(html)
const content = ContentState.createFromBlockArray(blocksFromHTML)
this.state = {
editorState: EditorState.createWithContent(content)
}
Как показано в примере Draft для convertFromHtml. Обратите внимание, что 0.9.1
версия не может импортировать изображения, тогда как 0.10.0
Можно.
В 0.10.0
createFromBlockArray
изменения в:
const content = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
)
Когда вам нужно инициировать редактор с простым текстом.
использование EditorState.createWithContent
а также ContentState.createFromText
методы. Рабочий пример - https://jsfiddle.net/levsha/3m5780jc/
constructor(props) {
super(props);
const initialContent = 'Some text';
const editorState = EditorState.createWithContent(ContentState.createFromText(initialContent));
this.state = {
editorState
};
}
Когда вам нужно запустить редактор с содержимым из строки разметки html.
использование convertFromHTML
а также ContentState.createFromBlockArray
, Рабочий пример - https://jsfiddle.net/levsha/8aj4hjwh/
constructor(props) {
super(props);
const sampleMarkup = `
<div>
<h2>Title</h2>
<i>some text</i>
</div>
`;
const blocksFromHTML = convertFromHTML(sampleMarkup);
const state = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
this.state = {
editorState: EditorState.createWithContent(state),
};
}
Если у вас есть массив строк, и вы хотите запустить редактор с некоторыми типами блоков по умолчанию draft.js.
Вы можете создать массив ContentBlocks
с конструктором new ContentBlock(...)
и передать его ContentState.createFromBlockArray
метод. Рабочий пример с unordered-list-item
- https://jsfiddle.net/levsha/uy04se6r/
constructor(props) {
super(props);
const input = ['foo', 'bar', 'baz'];
const contentBlocksArray = input.map(word => {
return new ContentBlock({
key: genKey(),
type: 'unordered-list-item',
characterList: new List(Repeat(CharacterMetadata.create(), word.length)),
text: word
});
});
this.state = {
editorState: EditorState.createWithContent(ContentState.createFromBlockArray(contentBlocksArray))
};
}
Когда вам нужно запустить редактор с контентом из ContentState
сырая структура JS.
Если вы ранее сохранили свое состояние контента в сырой структуре JS с convertToRaw
(прочтите этот ответ для деталей). Вы можете запустить редактор с convertFromRaw
метод. Рабочий пример - https://jsfiddle.net/levsha/tutc419a/
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createWithContent(convertFromRaw(JSON.parse(editorStateAsJSON)))
};
}
В простой, вы можете установить необработанный содержимое HTML в редакторе из начальной стадии или с использованием setState
в любое время, как показано ниже.
editorState: EditorState.createWithContent(ContentState.createFromBlockArray(convertFromHTML('<b>Program</b>')))
Импортируйте необходимые компоненты.
import { EditorState, ContentState, convertFromHTML } from 'draft-js'
Я обнаружил, что это чистый способ работы с богатым функционалом. Вы можете добавить больше плагинов в будущем, экспортировать свой контент как .md
и т.д., не меняя структуру вашего компонента.
import Draft from 'draft-js';
import DraftPasteProcessor from 'draft-js/lib/DraftPasteProcessor';
const { EditorState, ContentState } = Draft;
import Editor from 'draft-js-plugins-editor';
import createRichButtonsPlugin from 'draft-js-richbuttons-plugin';
const richButtonsPlugin = createRichButtonsPlugin();
class DescriptionForm extends React.Component {
state = {
editorState: this._getPlaceholder(),
}
_getPlaceholder() {
const placeholder = 'Write something here';
const contentHTML = DraftPasteProcessor.processHTML(placeholder);
const state = ContentState.createFromBlockArray(contentHTML);
return Draft.EditorState.createWithContent(state);
}
_onChange(editorState) {
this.setState({
editorState,
});
}
render () {
let { editorState } = this.state;
return (
<div>
<Editor
editorState={editorState}
onChange={this._onChange.bind(this)}
spellCheck={false}
plugins={[richButtonsPlugin, videoPlugin]}
/>
</div>
);
}
}
Вы можете установить начальное значение для вашего edtitorState, просто добавив следующий код, если вы хотите установить его в формате HTML
this.state = {
editorState: EditorState.createWithContent(
ContentState.createFromBlockArray(
convertFromHTML('<p>My initial content.</p>')
)
),
}
для Nextjs
import React, { Component } from 'react';
import { EditorState, convertToRaw, ContentState, convertFromHTML } from 'draft-
js';
import draftToHtml from 'draftjs-to-html';
import dynamic from 'next/dynamic';
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
const Editor = dynamic(
() => import('react-draft-wysiwyg').then(mod => mod.Editor),
{ ssr: false }
)
let htmlToDraft = null;
if (typeof window === 'object') {
htmlToDraft = require('html-to-draftjs').default;
}
export default class EditorConvertToHTML extends Component {
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createEmpty(),
contentState: ""
}
}
componentDidMount() {
const html = '<p>Hey this <strong>editor</strong> rocks d</p>';
const contentBlock = htmlToDraft(html);
console.log(contentBlock)
if (contentBlock) {
const contentState =
ContentState.createFromBlockArray(contentBlock.contentBlocks);
const editorState = EditorState.createWithContent(contentState);
console.log(editorState)
this.setState(
{
editorState: EditorState.createWithContent(
ContentState.createFromBlockArray(
convertFromHTML(html)
)
)
}
)
}
}
onEditorStateChange = (editorState) => {
this.setState({
editorState,
});
};
render() {
const { editorState } = this.state;
console.log(this.state.editorState.getCurrentContent())
return (
<div>
<Editor
editorState={editorState}
wrapperClassName="demo-wrapper"
editorClassName="demo-editor"
onEditorStateChange={this.onEditorStateChange}
/>
<textarea
disabled
value=
{draftToHtml(convertToRaw(editorState.getCurrentContent()))}
/>
</div>
);
}
}
вы можете использовать insertText()
insertContent(){
const contentState=editorState.getCurrentState();
const selection=editorState.getSelection();
const newContentState=Modifer.insertText(contentState,selection,'hello');
const nextEditorState=EditorState.push(editorState,newContentState,'insert-character')
setEditorState(nextEditorState)
}