【问题标题】:Does convertFromHTML support custom block types in Draft.js?convertFromHTML 是否支持 Draft.js 中的自定义块类型?
【发布时间】:2017-09-28 17:36:25
【问题描述】:

Here's a codepen example of the issue.

我添加了一个名为section 的自定义块类型,它用红色包裹了选定的文本。当您单击编辑工具栏中的section 时,它可以正常工作。但是,当与convertFromHTML 一起使用来呈现初始内容时,

const sampleMarkup = '<b>Bold text</b><br/>Section Testing:<section>dsasdasad</section><br/><i>Italic text</i>';

编辑器仍然将section 类型视为unstyle 类型。 convertFromHTML 是否支持初始渲染的自定义块类型?有解决办法吗?

代码:

      const {Editor,convertFromHTML,ContentState, EditorState,DefaultDraftBlockRenderMap, RichUtils} = Draft;

      const blockRenderMap = Immutable.Map({
    'section': {
        element: 'section'
    }
});

     const extendedBlockRenderMap = DefaultDraftBlockRenderMap.merge(blockRenderMap);

      class RichEditorExample extends React.Component {
        constructor(props) {
          super(props);
          const sampleMarkup =
  '<b>Bold text</b><br/>Section Testing:<section>dsasdasad</section><br/><i>Italic text</i>';

          const blocksFromHTML = convertFromHTML(sampleMarkup);
          const state = ContentState.createFromBlockArray(
            blocksFromHTML.contentBlocks,
            blocksFromHTML.entityMap
          );

          this.state = {editorState: EditorState.createWithContent(state)};

          this.focus = () => this.refs.editor.focus();
          this.onChange = (editorState) => this.setState({editorState});

          this.handleKeyCommand = (command) => this._handleKeyCommand(command);
          this.onTab = (e) => this._onTab(e);
          this.toggleBlockType = (type) => this._toggleBlockType(type);
          this.toggleInlineStyle = (style) => this._toggleInlineStyle(style);
        }

        _handleKeyCommand(command) {
          const {editorState} = this.state;
          const newState = RichUtils.handleKeyCommand(editorState, command);
          if (newState) {
            this.onChange(newState);
            return true;
          }
          return false;
        }

        _onTab(e) {
          const maxDepth = 4;
          this.onChange(RichUtils.onTab(e, this.state.editorState, maxDepth));
        }

        _toggleBlockType(blockType) {
          this.onChange(
            RichUtils.toggleBlockType(
              this.state.editorState,
              blockType
            )
          );
        }

        _toggleInlineStyle(inlineStyle) {
          this.onChange(
            RichUtils.toggleInlineStyle(
              this.state.editorState,
              inlineStyle
            )
          );
        }

        render() {
          const {editorState} = this.state;

          // If the user changes block type before entering any text, we can
          // either style the placeholder or hide it. Let's just hide it now.
          let className = 'RichEditor-editor';
          var contentState = editorState.getCurrentContent();
          if (!contentState.hasText()) {
            if (contentState.getBlockMap().first().getType() !== 'unstyled') {
              className += ' RichEditor-hidePlaceholder';
            }
          }

          return (
            <div className="RichEditor-root">
              <BlockStyleControls
                editorState={editorState}
                onToggle={this.toggleBlockType}
              />
              <InlineStyleControls
                editorState={editorState}
                onToggle={this.toggleInlineStyle}
              />
              <div className={className} onClick={this.focus}>
                <Editor
                  blockRenderMap={extendedBlockRenderMap}
                  blockStyleFn={getBlockStyle}
                  customStyleMap={styleMap}
                  editorState={editorState}
                  handleKeyCommand={this.handleKeyCommand}
                  onChange={this.onChange}
                  onTab={this.onTab}
                  placeholder="Tell a story..."
                  ref="editor"
                  spellCheck={true}
                />
              </div>
            </div>
          );
        }
      }

      // Custom overrides for "code" style.
      const styleMap = {
        CODE: {
          backgroundColor: 'rgba(0, 0, 0, 0.05)',
          fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
          fontSize: 16,
          padding: 2,
        },
      };

      function getBlockStyle(block) {
        switch (block.getType()) {
          case 'blockquote': return 'RichEditor-blockquote';
          default: return null;
        }
      }

      class StyleButton extends React.Component {
        constructor() {
          super();
          this.onToggle = (e) => {
            e.preventDefault();
            this.props.onToggle(this.props.style);
          };
        }

        render() {
          let className = 'RichEditor-styleButton';
          if (this.props.active) {
            className += ' RichEditor-activeButton';
          }

          return (
            <span className={className} onMouseDown={this.onToggle}>
              {this.props.label}
            </span>
          );
        }
      }

      const BLOCK_TYPES = [
        {label: 'H1', style: 'header-one'},
        {label: 'H2', style: 'header-two'},
        {label: 'H3', style: 'header-three'},
        {label: 'H4', style: 'header-four'},
        {label: 'H5', style: 'header-five'},
        {label: 'H6', style: 'header-six'},
        {label: 'Blockquote', style: 'blockquote'},
        {label: 'UL', style: 'unordered-list-item'},
        {label: 'OL', style: 'ordered-list-item'},
        {label: 'Code Block', style: 'code-block'},
        {label:'section',style:'section'},

      ];

      const BlockStyleControls = (props) => {
        const {editorState} = props;
        const selection = editorState.getSelection();
        const blockType = editorState
          .getCurrentContent()
          .getBlockForKey(selection.getStartKey())
          .getType();

        return (
          <div className="RichEditor-controls">
            {BLOCK_TYPES.map((type) =>
              <StyleButton
                key={type.label}
                active={type.style === blockType}
                label={type.label}
                onToggle={props.onToggle}
                style={type.style}
              />
            )}
          </div>
        );
      };

      var INLINE_STYLES = [
        {label: 'Bold', style: 'BOLD'},
        {label: 'Italic', style: 'ITALIC'},
        {label: 'Underline', style: 'UNDERLINE'},
        {label: 'Monospace', style: 'CODE'},
      ];

      const InlineStyleControls = (props) => {
        var currentStyle = props.editorState.getCurrentInlineStyle();
        return (
          <div className="RichEditor-controls">
            {INLINE_STYLES.map(type =>
              <StyleButton
                key={type.label}
                active={currentStyle.has(type.style)}
                label={type.label}
                onToggle={props.onToggle}
                style={type.style}
              />
            )}
          </div>
        );
      };

      ReactDOM.render(
        <RichEditorExample />,
        document.getElementById('target')
      );

【问题讨论】:

    标签: javascript reactjs draftjs


    【解决方案1】:

    是的。

    没有很好的文档记录,但是您需要将传递给Editor 的相同blockRenderMap 传递给convertFromHTML 函数的第三个参数。

    【讨论】:

      【解决方案2】:

      我知道这有点晚了,但我找到了here 的解决方案。我找不到在初始渲染时设置它的方法,但如果你根本无法设置它,你可以使用它。

      例子:

      // convertToHtml is a custom function which returns convertFromHTML(html)
      let htmlTranscript = convertToHtml(paragraphsArray)
      
      // important part
      htmlTranscript.contentBlocks[0] = htmlTranscript.contentBlocks[0].set('type', 'myType')
      
      const contentState = ContentState.createFromBlockArray(
                              htmlTranscript.contentBlocks,
                              htmlTranscript.entityMap
                          )
      
      this.setState({
          editorState: EditorState.createWithContent(contentState)
      })
      

      【讨论】:

        猜你喜欢
        • 2012-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-06
        • 1970-01-01
        • 2014-03-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多