docx_viewer_plus

A powerful Flutter package for viewing, editing, and sharing .docx (Microsoft Word) files directly inside your app. Built for Android, iOS, and macOS with zero external dependencies on native document libraries.

Features

  • DOCX Viewing — Parse and display .docx files with styles, tables, images, lists, and headings preserved

  • Rich Text Editing — Inline editing via WebView with bold, italic, underline, headings, alignment, lists, colors, links, and more

  • Customizable Toolbar — Show/hide individual buttons, reorder, add custom icons, control position (top/bottom)

  • Save & Share — Convert edited content back to .docx, save locally, or share via system share sheet

  • RTL Language Support — Arabic, Urdu, Hebrew, etc.

  • Localization — Built-in strings for English, Arabic, Urdu, Spanish; easy to add more

  • Isolate-Based Processing — Heavy parsing/packaging runs off the UI thread for smooth performance

Supported Formats

  • ✅ .docx (Microsoft Word Open XML)
  • ❌ .doc (Legacy binary Word format not supported)

Note: This package only supports modern DOCX files. Older DOC files must be converted to DOCX before use.

Installation


dependencies:
  docx_viewer_plus: ^1.1.3

Quick Start

Case 1: View-Only Mode


import 'package:docx_viewer_plus/docx_viewer_plus.dart';
DocxViewerWidget(

  filePath: '/path/to/document.docx',

  config: DocxViewerConfig(isReadOnly: true),

)

Case 2: Edit Mode with Save & Share


final _viewerKey = GlobalKey<DocxViewerWidgetState>();



DocxViewerWidget(

  key: _viewerKey,

  filePath: '/path/to/document.docx',

  config: DocxViewerConfig(

    toolbarPosition: ToolbarPosition.bottom,

  ),

)

// Save button

onPressed: () async {

  final path = await _viewerKey.currentState?.save(

    outputPath: '/path/to/output.docx',

  );

  if (path != null) print('Saved: $path');

},



// Share button

onPressed: () async {

  final bytes = await _viewerKey.currentState?.getDocxBytes();

  if (bytes == null) return;

  final dir = await getTemporaryDirectory();

  final file = File('${dir.path}/shared.docx');

  await file.writeAsBytes(bytes);
    await SharePlus.instance.share(

    ShareParams(files: [XFile(file.path)]),

  );

},

Case 3: Custom Toolbar Options


DocxViewerWidget(

  filePath: '/path/to/document.docx',

  config: DocxViewerConfig(

    enabledOptions: {

      ToolbarOption.bold,

      ToolbarOption.italic,

      ToolbarOption.underline,

      ToolbarOption.heading1,

      ToolbarOption.heading2,

      ToolbarOption.alignLeft,

      ToolbarOption.alignCenter,

      ToolbarOption.alignRight,

    },

  ),

)

Case 4: RTL Language Support


DocxViewerWidget(

  filePath: '/path/to/arabic-doc.docx',

  config: DocxViewerConfig(

    forceTextDirection: TextDirection.rtl,

    strings: DocxViewerStrings.arabic,
        toolbarPosition: ToolbarPosition.bottom,

  ),

)

Case 5: Load from Bytes (Asset/Network)


final service = DocxService();

final bytes = await rootBundle.load('assets/doc.docx');

await service.loadFromBytes(

  bytes.buffer.asUint8List(),

  fileName: 'document.docx',

);

Case 6: Listen for Content Changes


DocxViewerWidget(

  filePath: '/path/to/document.docx',

  onContentChanged: (html) {

    print('Content changed, length: ${html.length}');

  },

)

Case 7: Custom Save Callback


DocxViewerWidget(

  filePath: '/path/to/document.docx',

  onSave: () async {

    final path = await pickSaveLocation();
        return path;

  },

)

API Reference

DocxViewerWidget

| Parameter | Type | Default | Description |

|-----------|------|---------|-------------|

| filePath | String | required | Path to .docx |

| config | DocxViewerConfig | const | Viewer config |

| onSave | Future<String?> Function()? | null | Save callback |

| onContentChanged | void Function(String)? | null | Change listener |

DocxViewerWidgetState Methods

| Method | Returns | Description |

|--------|---------|-------------|

| save({String? outputPath}) | Future<String?> | Save to file |

| getDocxBytes() | Future<Uint8List?> | Get raw bytes |

| service | DocxService | Access service |

DocxService

| Method | Returns | Description |

|--------|---------|-------------|

| loadFromPath(String) | Future

| loadFromBytes(Uint8List) | Future

| saveDocx({String?, String?}) | Future<String?> | Save .docx |

| getDocxBytes({String?}) | Future<Uint8List?> | Get bytes |

| hasDocument | bool | Doc is loaded |

| isModified | bool | Edits were made |

Platform Support

| Platform | Status | Notes |

|----------|--------|-------|

| Android | Supported | Android WebView |

| iOS | Supported | WKWebView |

| macOS | Supported | WKWebView |

| Web | Not supported | Requires native WebView |

Troubleshooting

Blank DOCX on share/save: Ensure you call getDocxBytes()

or save() AFTER the document has fully loaded. Check

service.hasDocument && service.html.isNotEmpty. The

widget’s getDocxBytes() includes automatic retry and

fallback to original bytes.

Images not appearing: Embedded images are preserved.

External URLs are not supported.

Large documents: Parsing runs in isolates. Very large

documents (>5MB) may take a few seconds to load.

License

BSD-3-Clause. See LICENSE for details.

Author

Muslim Bin Sohail — muslimbinsohail@gmail.com

Libraries

docx_viewer_plus