2017-12-27 100 views
4

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

我的编辑从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时,upl成功插入上传的图像到编辑器中。我试图做到这一点下面的方法上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 is not a function

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

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

你知道为什么吗?

编辑1

我设法通过改变insertImageMyEditor到一定程度剿错误:

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

最终通过查看该反应-草案所见即所得的controlls(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}); 
    };