Search results

Import in React DocumentEditor component

03 Aug 2021 / 7 minutes to read

In Document Editor, the documents are stored in its own format called Syncfusion Document Text (SFDT).

The following example shows how to open SFDT data in Document Editor.

Source
Preview
index.jsx
index.tsx
index.html
Copied to clipboard
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { DocumentEditorComponent } from '@syncfusion/ej2-react-documenteditor';
export class Default extends React.Component {
    componentDidMount() {
        let sfdt = `{
        "sections": [
        {
            "blocks": [
                {
                    "inlines": [
                        {
                            "characterFormat": {
                                "bold": true,
                                "italic": true
                            },
                            "text": "Hello World"
                        }
                    ]
                }
            ],
            "headersFooters": {
            }
        }
    ]
    }`;
        setTimeout(() => {
            this.documenteditor.open(sfdt);
        });
    }
    render() {
        return (<DocumentEditorComponent id="container" ref={(scope) => { this.documenteditor = scope; }}/>);
    }
}
ReactDOM.render(<Default />, document.getElementById('sample'));
Copied to clipboard
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import {
    DocumentEditorComponent, DocumentEditor
} from '@syncfusion/ej2-react-documenteditor';

export class Default extends React.Component<{}, {}> {
    public documenteditor: DocumentEditorComponent;

    public componentDidMount(): void {
        let sfdt: string = `{
        "sections": [
        {
            "blocks": [
                {
                    "inlines": [
                        {
                            "characterFormat": {
                                "bold": true,
                                "italic": true
                            },
                            "text": "Hello World"
                        }
                    ]
                }
            ],
            "headersFooters": {
            }
        }
    ]
    }`;

    setTimeout(()=>{
        this.documenteditor.open(sfdt);
    });
    }

    render() {
        return (
            <DocumentEditorComponent id="container" ref={(scope) => { this.documenteditor = scope; }} />
        );
    }
}
ReactDOM.render(<Default />, document.getElementById('sample'));
Copied to clipboard
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Syncfusion React Button</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Essential JS 2 for React Components" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-documenteditor/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-documenteditor/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-buttons/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-dropdowns/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-inputs/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-splitbuttons/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-lists/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-navigations/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-popups/styles/fabric.css" rel="stylesheet" /> 
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
        <div id='sample'>
            <div id='loader'>Loading....</div>
        </div>
</body>

</html>

Import document from local machine

The following example shows how to import document from local machine.

Source
Preview
index.jsx
index.tsx
index.html
Copied to clipboard
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { DocumentEditorComponent, } from '@syncfusion/ej2-react-documenteditor';
export class Default extends React.Component {
    onImportClick() {
        document.getElementById('file_upload').click();
    }
    onFileChange(e) {
        if (e.target.files[0]) {
            let file = e.target.files[0];
            if (file.name.substr(file.name.lastIndexOf('.')) === '.sfdt') {
                let fileReader = new FileReader();
                fileReader.onload = (e) => {
                    let contents = e.target.result;
                    let proxy = this;
                    proxy.documenteditor.open(contents);
                };
                fileReader.readAsText(file);
                this.documenteditor.documentName = file.name.substr(0, file.name.lastIndexOf('.'));
            }
        }
    }
    render() {
        return (<div>
      <input type='file' id='file_upload' accept='.sfdt' onChange={this.onFileChange.bind(this)}/>
        <button onClick={this.onImportClick.bind(this)}>Import</button>
        <DocumentEditorComponent id="container" ref={scope => {
            this.documenteditor = scope;
        }}/>
      </div>);
    }
}
ReactDOM.render(<Default />, document.getElementById('sample'));
Copied to clipboard
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import {
  DocumentEditorComponent,
  DocumentEditor,
} from '@syncfusion/ej2-react-documenteditor';

export class Default extends React.Component<{}, {}> {
  public documenteditor: DocumentEditorComponent;

  onImportClick(): void {
    document.getElementById('file_upload').click();
  }

  onFileChange(e: any): void {
    if (e.target.files[0]) {
      let file = e.target.files[0];
      if (file.name.substr(file.name.lastIndexOf('.')) === '.sfdt') {
        let fileReader: FileReader = new FileReader();
        fileReader.onload = (e: any) => {
          let contents: string = e.target.result;
          let proxy:any=this;
          proxy.documenteditor.open(contents);
        };
        fileReader.readAsText(file);
        this.documenteditor.documentName = file.name.substr(
          0,
          file.name.lastIndexOf('.')
        );
      }
    }
  }
  render() {
    return (
      <div>
      <input type='file' id='file_upload' accept='.sfdt' onChange={this.onFileChange.bind(this)}/>
        <button onClick={this.onImportClick.bind(this)}>Import</button>
        <DocumentEditorComponent
          id="container"
          ref={scope => {
            this.documenteditor = scope;
          }}
        />
      </div>
    );
  }
}
ReactDOM.render(<Default />, document.getElementById('sample'));
Copied to clipboard
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Syncfusion React Button</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Essential JS 2 for React Components" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-documenteditor/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-documenteditor/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-buttons/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-dropdowns/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-inputs/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-splitbuttons/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-lists/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-navigations/styles/fabric.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-popups/styles/fabric.css" rel="stylesheet" /> 
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
        <div id='sample'>
            <div id='loader'>Loading....</div>
        </div>
</body>

</html>

Convert word documents into SFDT

You can convert word documents into SFDT format using the .NET Standard library “Syncfusion.EJ2.DocumentEditor” by the web API service implementation. This library helps you to convert word documents (.dotx,.docx,.docm,.dot,.doc), rich text format documents (.rtf), and text documents (.txt) into SFDT format.

Note: The Syncfusion Document editor component’s document pagination (page-by-page display) can’t be guaranteed for all the Word documents to match the pagination of Microsoft Word application. For more information about why the document pagination (page-by-page display) differs from Microsoft Word

Please refer the following example for converting word documents into SFDT.

Copied to clipboard
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import {
  DocumentEditorComponent,
  DocumentEditor,
} from '@syncfusion/ej2-react-documenteditor';

export class Default extends React.Component<{}, {}> {
  public documenteditor: DocumentEditorComponent;

  onImportClick(): void {
    document.getElementById('file_upload').click();
  }

  onFileChange(e: any): void {
     if (e.target.files[0]) {
        let file = e.target.files[0];
        if (file.name.substr(file.name.lastIndexOf('.')) !== '.sfdt') {
            loadFile(file);
        }
    }
  }

  loadFile(file: File): void {
    let ajax: XMLHttpRequest = new XMLHttpRequest();
    ajax.open('POST', 'https://localhost:4000/api/documenteditor/Import', true);
    ajax.onreadystatechange = () => {
      if (ajax.readyState === 4) {
        if (ajax.status === 200 || ajax.status === 304) {
          // open SFDT text in document editor
          documenteditor.open(ajax.responseText);
        }
      }
    };
    let formData: FormData = new FormData();
    formData.append('files', file);
    ajax.send(formData);
  }
  render() {
    return (
      <div>
        <input type="file" id="file_upload" accept=".dotx,.docx,.docm,.dot,.doc,.rtf,.txt,.xml,.sfdt" onChange={this.onFileChange.bind(this)} />
        <button onClick={this.onImportClick.bind(this)}>Import</button>
        <DocumentEditorComponent id="container" ref={scope => {
            this.documenteditor = scope; }} />
      </div>
    );
  }
}
ReactDOM.render(<Default />, document.getElementById('sample'));
Copied to clipboard
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { DocumentEditorComponent, } from '@syncfusion/ej2-react-documenteditor';
export class Default extends React.Component {
    onImportClick() {
        document.getElementById('file_upload').click();
    }
    onFileChange(e) {
        if (e.target.files[0]) {
            let file = e.target.files[0];
            if (file.name.substr(file.name.lastIndexOf('.')) !== '.sfdt') {
                loadFile(file);
            }
        }
    }
    loadFile(file) {
        let ajax = new XMLHttpRequest();
        ajax.open('POST', 'https://localhost:4000/api/documenteditor/Import', true);
        ajax.onreadystatechange = () => {
            if (ajax.readyState === 4) {
                if (ajax.status === 200 || ajax.status === 304) {
                    // open SFDT text in document editor
                    documenteditor.open(ajax.responseText);
                }
            }
        };
        let formData = new FormData();
        formData.append('files', file);
        ajax.send(formData);
    }
    render() {
        return (<div>
        <input type="file" id="file_upload" accept=".dotx,.docx,.docm,.dot,.doc,.rtf,.txt,.xml,.sfdt" onChange={this.onFileChange.bind(this)}/>
        <button onClick={this.onImportClick.bind(this)}>Import</button>
        <DocumentEditorComponent id="container" ref={scope => {
            this.documenteditor = scope;
        }}/>
      </div>);
    }
}
ReactDOM.render(<Default />, document.getElementById('sample'));

Here’s how to handle the server-side action for converting word document in to SFDT.

Copied to clipboard
[AcceptVerbs("Post")]
public string Import(IFormCollection data)
{
    if (data.Files.Count == 0)
        return null;
    Stream stream = new MemoryStream();
    IFormFile file = data.Files[0];
    int index = file.FileName.LastIndexOf('.');
    string type = index > -1 && index < file.FileName.Length - 1 ?
        file.FileName.Substring(index) : ".docx";
    file.CopyTo(stream);
    stream.Position = 0;

    WordDocument document = WordDocument.Load(stream, GetFormatType(type.ToLower()));
    string sfdt = Newtonsoft.Json.JsonConvert.SerializeObject(document);
    document.Dispose();
    return sdft;
}

internal static FormatType GetFormatType(string format)
{
    if (string.IsNullOrEmpty(format))
        throw new NotSupportedException("EJ2 DocumentEditor does not support this file format.");
    switch (format.ToLower()) {
        case ".dotx":
        case ".docx":
        case ".docm":
        case ".dotm":
            return FormatType.Docx;
        case ".dot":
        case ".doc":
            return FormatType.Doc;
        case ".rtf":
            return FormatType.Rtf;
        case ".txt":
            return FormatType.Txt;
        case ".xml":
            return FormatType.WordML;
        default:
            throw new NotSupportedException("EJ2 DocumentEditor does not support this file format.");
    }
}

Compatibility with Microsoft Word

Syncfusion Document editor is a minimal viable Word document viewer/editor product for web applications. As most compatible Word editor, the product vision is adding valuable feature sets of Microsoft Word, and not to cover 100% feature sets of Microsoft Word desktop application. You can even see the feature sets difference between Microsoft Word desktop and their Word online application. So kindly don’t misunderstand this component as a complete replacement for Microsoft Word desktop application and expect 100% feature sets of it.

How Syncfusion accepts the feature request for Document editor

Syncfusion accepts new feature request as valid based on feature value and technological feasibility, then plan to implement unsupported features incrementally in future releases in a phase-by-phase manner.

How to report the problems in Document editor

You can report the problems with displaying, or editing Word documents in Document editor component through support forumDirect-Trac, or feedback portal. Kindly share the Word document for replicating the problem easily in minimal time. If you have confidential data, you can replace it and attach the document.

Why the document pagination differs from Microsoft Word

For your understanding about the Word document structure and the workflow of Word viewer/editor components, the Word document is a flow document in which content will not be preserved page by page; instead, the content will be preserved sequentially like a HTML file. Only the Word viewer/editor paginates the content of the Word document page by page dynamically, when opened for viewing or editing and this page-wise position information will not be preserved in the document level (it is Word file format specification standard). Syncfusion Document editor component also does the same.

At present there is a known technical limitation related to slight difference in text size calculated using HTML element based text measuring approach. Even though the text size is calculated with correct font and font size values, the difference lies; it is as low as 0.00XX to 0. XXXX values compared to that of Microsoft Word application’s display. Hence the document pagination (page-by-page display) can’t be guaranteed for all the Word documents to match the pagination of Microsoft Word application.

How Syncfusion address the document pagination difference compared to Microsoft Word

The following table illustrates the reasons for pagination (page-by-page display) difference compared to Microsoft Word in your documents and how Syncfusion address it.

Root causes How is it solved?
Any mistake (wrong behavior handled) in lay outing the supported elements and formatting  Customer can report to Syncfusion support and track the status through bug report link.  Syncfusion fixes the bugs in next possible weekly patch release and service pack or main releases. 
Font missing in deployment environment Customer can either report to Syncfusion support and get suggestion or solve it on their own by installing the missing fonts in their deployment environment.
Any unsupported elements or formatting present in your document  Customer can report to Syncfusion support and track the status through feature request link.   Syncfusion implements unsupported features incrementally in future releases based on feature importance, customer interest, efforts involved, and technological feasibility. Also, suggests alternate approach for possible cases.
Technical limitation related to framework   For example, there is a known case with slight fractional difference in text size measured using HTML and Microsoft Word’s display. Customer can report to Syncfusion support and track the status through feature request link.  Syncfusion does research about alternate approaches to overcome the technical limitation/behaviors and process it same as a feature. >Note: Here the challenge is, time schedule for implementation varies based on the alternate solution and its reliability.

See Also