Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading HTML content into editor #41

Closed
alagos opened this issue Nov 7, 2016 · 16 comments
Closed

Loading HTML content into editor #41

alagos opened this issue Nov 7, 2016 · 16 comments

Comments

@alagos
Copy link

alagos commented Nov 7, 2016

Maybe is a basic question (actually I guess is not related with your current draft based editor), but I don't get at all how draftjs works. I've been trying to load some html using the demo as example and so far I've tried something like this:

import React from 'react'
import { Modal } from 'react-bootstrap'
import { Editor } from 'react-draft-wysiwyg';
import draftToHtml from 'draftjs-to-html';
import { convertFromHTML, ContentState, convertToRaw } from 'draft-js';


export default class EditDescriptionModal extends React.Component {

  constructor(props) {
    super(props);
    this.state = {editorContent: this._getInitialHTML()};
  }

  _getInitialHTML() {
    const contentBlocks = convertFromHTML('<p>Hello world</p>');
    const contentState = ContentState.createFromBlockArray(contentBlocks);
    return convertToRaw(contentState);
  }

  onEditorChange(editorContent) {
    console.log(draftToHtml(editorContent))
    this.setState({ editorContent });
  };

  render(){
    const { editorContent } = this.state;
    return(
      <Modal  show={this.props.showModal} onHide={this.props.onClose}
              bsSize="large" >
        <form className="form-horizontal" >
          <Modal.Header closeButton>
            <Modal.Title>Edit description</Modal.Title>
          </Modal.Header>
          <Modal.Body>
            <div className="demo-editorSection">
              <div className="demo-editorWrapper">
                <Editor
                  rawContentState={editorContent}
                  toolbarClassName="demo-toolbar"
                  wrapperClassName="demo-wrapper"
                  editorClassName="demo-editor"
                  onChange={this.onEditorChange.bind(this)}
                  toolbarAlwaysVisible
                />
              </div>
            </div>
          </Modal.Body>
          <Modal.Footer>
            <button type="submit" className="btn btn-info">Submit</button>
            <button type="button" className="btn"
                    onClick={this.props.onClose}>Close</button>
          </Modal.Footer>
        </form>
      </Modal>
    )
  }
}

So is supposed it should display that <p>Hello world</p> as initial editor content passing to the rawContentState of the Editor component, but I think I'm wrong.
In any case, if I add some text to the editor, is correctly converted to HTML in the onEditorChange function. What I'm doing wrong here?.
BTW, kudos for the great work done

@jpuri
Copy link
Owner

jpuri commented Nov 7, 2016

@alagos
Copy link
Author

alagos commented Nov 7, 2016

@jpuri yes, actually, that's the specific example I'm basing of. Instead of using sampleEditorContent to load the content in rawContentState={sampleEditorContent} I loaded it from the state and I almost copy/pasted the content from https://github.com/jpuri/react-draft-wysiwyg/blob/master/docs/src/util/sampleEditorContent.js to my _getInitialHTML function to load the initial data for the state, but is not working.
Not sure if has something to do, but I'm using 0.2.1 version.

@jpuri
Copy link
Owner

jpuri commented Nov 7, 2016

ok try to do a console log and check whats coming in editorContent after this line const { editorContent } = this.state;.

@alagos
Copy link
Author

alagos commented Nov 7, 2016

That's the result with console.log(JSON.stringify(editorContent));:

{
  "entityMap": {},
  "blocks": [
    {
      "key": "1n9j8",
      "text": "Hello world",
      "type": "unstyled",
      "depth": 0,
      "inlineStyleRanges": [],
      "entityRanges": [],
      "data": {}
    }
  ]
}

and after I click the editor to write something and render is reevaluated, the result is:

{
  "entityMap": {},
  "blocks": [
    {
      "key": "a5b87",
      "text": "",
      "type": "unstyled",
      "depth": 0,
      "inlineStyleRanges": [],
      "entityRanges": [],
      "data": {}
    }
  ]
}

@jpuri
Copy link
Owner

jpuri commented Nov 8, 2016

Its looks like editor is re-mounting in each render - which I do not expect to be the case, it may be an issue with Modal component.

Ideally editor should have been initialized only once but apparently its content are reset second time also.

@ytwater
Copy link

ytwater commented Nov 11, 2016

I ran into the same problem where my editorContents was null the first time I rendered, then was populated on a second render. A quick and dirty fix of not rendering until I know the data is there worked for me.

` render() {

const { editorContents } = this.state;

if (!editorContents) {
  return <div />;
}

return (
  <div>
    <div className="demo-label">
      Editor with output generated in HTML.
    </div>
    <div className="demo-editorSection">
      <Editor
        toolbarClassName="demo-toolbar"
        wrapperClassName="demo-wrapper"
        editorClassName="demo-editor"
        rawContentState={editorContents}
        onChange={this.onEditorChange.bind(this)}
        toolbar={{
          options: ['inline', 'blockType', 'textAlign', 'link', 'remove', 'history'],
          inline: {
            options: ['bold', 'italic', 'underline', 'strikethrough'],
          },
        }}
      />
    </div>
  </div>
);

}`

@jpuri
Copy link
Owner

jpuri commented Dec 9, 2016

@ytwater: you can also check new contentState property (detailed in docs) it can be used not only for initializing but also changing editor content.

@jpuri
Copy link
Owner

jpuri commented Dec 9, 2016

@alagos: is your issue resolved, can I do something more to help it ?

@alagos
Copy link
Author

alagos commented Dec 9, 2016

@jpuri at the end I moved to another editor as I couldn't figure out what was going on, sorry about that. Anyway thanks for the help :)

@alagos alagos closed this as completed Dec 9, 2016
@kamote
Copy link

kamote commented Jan 13, 2017

same issue here using react-bootstrap modal

@iphonic
Copy link

iphonic commented Oct 4, 2017

For ones who are wondering how to initialize it with HTML content instead of empty here is the way you need to generate editorState with the content you have, to init editorState there is a function in draft-js EditorState component and I am using a converter draft-js-import-html which allows to generate contentState out of HTML content, see below

import {EditorState, ContentState, convertFromHTML, convertToRaw} from 'draft-js';
import {stateFromHTML} from 'draft-js-import-html';

constructor(props) {
    super(props);
    var contentState = stateFromHTML(props.input.value);
    editorState = EditorState.createWithContent(contentState);
    this.state = {editorState: editorState};
}

Above works for me.

@lvian
Copy link

lvian commented Jan 18, 2018

@iphonic Thanks for posting, was having problems loading the content stored in the DB back into the editor and your post solved it.

@andrew-w0711
Copy link

@iphonic Thanks for your answer

@Ranganathan95
Copy link

Ranganathan95 commented Dec 29, 2019

@jpuri & @iphonic , I tried statefromHTML and also convertFromHTML from draft-js. both were working fine, but when the content has underline/subscript/superscript content, it was rendered as normal text. Is there any work-around available?
Note: Bold and italic styles working fine.

@swapster
Copy link

swapster commented Oct 15, 2020

when the content has underline/subscript/superscript content, it was rendered as normal text

The same problem. Is there any solution?

@elebumm
Copy link

elebumm commented Oct 26, 2020

@iphonic's result worked for me perfectly. I am using functional components though so here is my solution:

  const [editorState, setEditorState] = useState(EditorState.createEmpty());

  useEffect(() => {
   // automatedMessage is the html string I am fetching from my server
    if (automatedMessage) {
      let contentState = stateFromHTML(automatedMessage.message); //automatedMessage.message being "<p>Test</p>"
      setEditorState(EditorState.createWithContent(contentState));
    }
  }, [automatedMessage]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants