2017-12-27 6 views
4

Über meine einfache draft.js project Ich versuche, ein Bild von einem externen Formular in den Inhalt des Editors hochgeladen. Der Editor, den ich verwende, ist der react-draft-wysiwyg , der intern den draftjs-Editor verwendet.Draft.js kann hochgeladenes Bild nicht von externem Formular einfügen

ist Mein Redakteur von den MyEditor.js gemacht:

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; 

Und ich habe folgendes Uploader:

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; 

Und ich habe und die App.js, die die Quellen für die gesamte enthält app:

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; 

Was ich erreichen möchte ist, wenn ein Bild aus dem Formular hochgeladen wird, wenn Upl erfolgreich hochgeladen, um das hochgeladene Bild in den Editor einzufügen. Ich versuche, dass auf MyEditor.js mit dem folgenden Verfahren zu erreichen:

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}); 
     }; 

Aber aus irgendeinem Grund bekomme ich den Fehler:

editorState.getImmutable is not a function

über meine Browser-Konsole. Eine weitere Untersuchung hat ergeben, dass dies in der folgenden Methode geschieht:

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

Haben Sie eine Idee warum?

Edit 1

ich es geschafft, etwas um den Fehler zu unterdrücken, indem die insertImage in MyEditor ausgetauscht wurden durch:

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

Dann auf App.js ich die uploadCallback in geändert:

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

Aber für aus irgendeinem Grund kann ich das Bild nicht im Inhalt des Herausgebers sehen. Hast du eine Ahnung warum?

Edit 2

Ich habe versucht, den Rückruf onEditorStateChange und kein Fehler geworfen wird zu verwenden, aber ich bekomme immer noch keine aktualisierte Inhalte in Draft.js Editor. Die Folge insertImage ist diese:

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); 
    }; 

Antwort

1

Am Ende, indem man über die Reaktion-draft-wysıwyg des controlls (https://github.com/jpuri/react-draft-wysiwyg/blob/master/src/controls/Image/index.js) hat eine Methode namens:

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(); 
    }; 

So basiert über Angebote Dieses man tun :

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}); 
    }; 
Verwandte Themen