首页 文章

Draft.js无法从外部表单插入上传的图像

提问于
浏览
4

在我的简单draft.js project我尝试将从外部表单上传的图像插入到编辑器的内容中 . 我使用的编辑器是内部使用draftjs编辑器的react-draft-wysiwyg .

我的编辑器是从MyEditor.js渲染的:

import React, { Component } from 'react';
import { EditorState,AtomicBlockUtils } from 'draft-js';
import { Editor } from 'react-draft-wysiwyg';

import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';


class MyEditor extends Component {
    state = {
        editorState: EditorState.createEmpty(),
    }

    onEditorStateChange: Function = (editorState) => {
      this.setState({
        editorState,
      });
    };

    uploadCallback(file,callback) {
      return new Promise( (resolve, reject) => {
        var reader = new window.FileReader();
        reader.onloadend= () => { 
          fetch('http://localhost:9090/image',{
            method: 'POST',
            headers: {
              'Accept': 'application/json',
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              name: file.name,
              data: reader.result,
            }),
          })
          .then((resp) => resp.json()) 
          .then((data)=>{
              console.log('Uploaded Data',data);
              const imageUrl='http://localhost:9090/image/'+data.name;
              resolve({data:{ link: imageUrl } });
          });
        }
        reader.readAsDataURL(file);
      });
    }

    insertImage(url) {
      console.log(this);
      const contentState = this.state.editorState.getCurrentContent();
      const contentStateWithEntity = contentState.createEntity(
        'image',
        'IMMUTABLE',
        { src: url },
      );
      const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
      const newEditorState = EditorState.set(
        contentState,
        { currentContent: contentStateWithEntity },
      );
      const state=AtomicBlockUtils.insertAtomicBlock(newEditorState, entityKey, ' ');
      this.setState({editorState:state});
    };

    render() {
      const { editorState } = this.state;
      const config={
        image: { uploadCallback: this.uploadCallback }
      }
      return (
          <Editor
              editorState={editorState}
              wrapperClassName="demo-wrapper"
              editorClassName="demo-editor"
              onEditorStateChange={this.onEditorStateChange}
              toolbar={ config }
          />
      );
    }
}

export default MyEditor;

我有以下上传者:

import React, { Component } from 'react';

class UploadForm extends Component {

    state={
      lastImgUploaded:""
    };


    onChange(event){
        event.preventDefault();
        console.log("File Changed");

        const file=event.target.files[0];

        const reader = new window.FileReader();
        reader.onloadend= () => { 
          fetch('http://localhost:9090/image',{
            method: 'POST',
            headers: {
              'Accept': 'application/json',
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              name: file.name,
              data: reader.result,
            }),
          })
          .then((resp) => resp.json()) 
          .then((data) => {
              console.log('Uploaded Data',data);
              const imageUrl='http://localhost:9090/image/'+data.name;
              if(this.props.uploadCallback){ this.props.uploadCallback(imageUrl); }
              this.setState({'lastImgUploaded':imageUrl})
          });
        }

        reader.readAsDataURL(file);
    }

    render(){
       return (
       <div>
            <h3>Upload an image and set it into the editor</h3>
            <input type="file" onChange={ this.onChange.bind(this) } name="file"/>
        </div>);
    }
}

export default UploadForm;

我有和包含整个应用程序源的App.js:

import React, { Component } from 'react';
import Editor from './MyEditor';
import UploadForm from './UploadForm';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  state={
    uploadedImage:""
  };

  uploadCallback(link){
    this.setState({'uploadedImage':link});
    this.__editor.insertImage(link).bind(this.__editor);
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <div className="App-editor">
          <Editor ref={ (editor) => {this.__editor=editor; } } />
        </div>
        <div className="SideBar">
          <div className="LastUpload">
            <h3>Last Uploaded Image</h3>
            <img src={this.state.uploadedImage} />
          </div>
          <div className="sideBarUpload">
            <UploadForm  uploadCallback={ this.uploadCallback.bind(this) }/>
          </div>
        </div>
      </div>
    );
  }
}

export default App;

我想要实现的是当图像从表单上传到我的api时,成功上传时将上传的图像插入到编辑器中 . 我尝试在 MyEditor.js 上使用以下方法实现:

insertImage(url) {
          console.log(this);
          const contentState = this.state.editorState.getCurrentContent();
          const contentStateWithEntity = contentState.createEntity(
            'image',
            'IMMUTABLE',
            { src: url },
          );
          const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
          const newEditorState = EditorState.set(
            contentState,
            { currentContent: contentStateWithEntity },
          );
          const state=AtomicBlockUtils.insertAtomicBlock(newEditorState, entityKey, ' ');
          this.setState({editorState:state});
        };

但由于某种原因,我得到错误:

editorState.getImmutable不是函数

在我的浏览器控制台上进一步调查证明,这种情况发生在以下方法中:

const newEditorState = EditorState.set(
        contentState,
        { currentContent: contentStateWithEntity },
      );

你知道为什么吗?

编辑1

我设法通过将 MyEditor 中的 insertImage 更改为:

insertImage: Function = (url) => {
  const editorState = this.state.editorState;
  const block = new ContentBlock({
    key: genKey(),
    type: 'unstyled',
    text: '<img src="'.concat(url).concat('"></img>'),
  });

然后在 App.js 我将 uploadCallback 更改为:

uploadCallback(link){
  this.setState({'uploadedImage':link});
  console.log(this.__editor);
  this.__editor.insertImage(link);
}

但由于某种原因,我无法将图像看到编辑器的内容中 . 你知道为什么吗?

编辑2

我尝试使用回调 onEditorStateChange 并且没有抛出任何错误但我仍然没有获得Draft.js编辑器的更新内容 . 结果 insertImage 是这一个:

insertImage: Function = (url) => {
      console.log("Inserting Image");
      const editorState = this.state.editorState;
      const block = new ContentBlock({
        key: genKey(),
        type: 'unstyled',
        text: url,
      });

      const contentState = editorState.getCurrentContent();
      const blockMap = contentState.getBlockMap().set(block.key, block);                   
      const newState = EditorState.push(editorState, contentState.set('blockMap', blockMap));
      this.onEditorStateChange(newState);
    };

1 回答

  • 1

    最后,通过查看react-draft-wysiwyg的控件(https://github.com/jpuri/react-draft-wysiwyg/blob/master/src/controls/Image/index.js)有一个名为的方法:

    addImage: Function = (src: string, height: string, width: string, alt: string): void => {
        const { editorState, onChange, config } = this.props;
        const entityData = { src, height, width };
        if (config.alt.present) {
          entityData.alt = alt;
        }
        const entityKey = editorState
          .getCurrentContent()
          .createEntity('IMAGE', 'MUTABLE', entityData)
          .getLastCreatedEntityKey();
        const newEditorState = AtomicBlockUtils.insertAtomicBlock(
          editorState,
          entityKey,
          ' ',
        );
        onChange(newEditorState);
        this.doCollapse();
      };
    

    所以基于这个做这个:

    insertImage: Function = (url) => {
          console.log("Inserting Image",this.__editor);
          const editorState = this.state.editorState;
          const entityData = { src:url, height: 300, width: 300, };
          const contentStateWithEntity=editorState.getCurrentContent().createEntity('IMAGE', 'IMMUTABLE', entityData);
    
          const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
    
          let newEditorState = EditorState.set(editorState, { currentContent: contentStateWithEntity },);
          newEditorState = AtomicBlockUtils.insertAtomicBlock(editorState,entityKey,' ',);
          this.setState({editorState:newEditorState});
        };
    

相关问题