Skip to content

How to: display an editor

Matt Carroll edited this page Apr 6, 2021 · 1 revision

To display an editor, you first need a Document to display within the editor.

Compose a document

Documents are currently entirely in-memory.

You can compose a document with code similar to the following:

return MutableDocument(nodes: [
    ParagraphNode(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: 'Super Editor'),
      metadata: {
        'blockType': 'header1',
      },
    ),
    ParagraphNode(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: 'Rich text and multimedia'),
      metadata: {
        'blockType': 'header2',
      },
    ),
    ParagraphNode(
        id: DocumentEditor.createNodeId(),
        text: AttributedText(
          text: _loremIpsum1,
          attributions: [
            SpanMarker(attribution: 'bold', offset: 20, markerType: SpanMarkerType.start),
            SpanMarker(attribution: 'bold', offset: 80, markerType: SpanMarkerType.end),
          ],
        ),
        metadata: {
          'textAlign': 'justify',
        }),
    ParagraphNode(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: _loremIpsum1),
      metadata: {
        'textAlign': 'center',
      },
    ),
    ParagraphNode(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: 'This is some important quotation about something.'),
      metadata: {
        'blockType': 'blockquote',
      },
    ),
    ParagraphNode(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: _loremIpsum1),
      metadata: {
        'textAlign': 'right',
      },
    ),
    ListItemNode.unordered(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: 'This is the 1st list item.'),
    ),
    ListItemNode.unordered(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: 'This is the 2nd list item.'),
    ),
    ListItemNode.unordered(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: 'This is the 3rd list item.'),
      indent: 1,
    ),
    HorizontalRuleNode(id: DocumentEditor.createNodeId()),
    ListItemNode.ordered(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: 'This is the 1st list item.'),
    ),
    ListItemNode.ordered(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: 'This is the 2nd list item.'),
    ),
    ListItemNode.ordered(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: 'This is the 3rd list item.'),
      indent: 1,
    ),
    ParagraphNode(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: _loremIpsum2),
    ),
    ImageNode(
      id: DocumentEditor.createNodeId(),
      imageUrl:
          'https://images.unsplash.com/photo-1612099453097-26a809f51e96?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80',
    ),
    ParagraphNode(
      id: DocumentEditor.createNodeId(),
      text: AttributedText(text: _loremIpsum3),
    ),
  ]);

Display an editor

Standard Editor

Display a standard editor with default behavior and rendering:

  // Create a DocumentEditor in initState() or some other location
  // that only runs once.
  final documentEditor = DocumentEditor(document: doc);

  // In a build() method, create the Editor widget.
  return Editor.standard(
    editor: documentEditor,
    showDebugPaint: showDebugPaint, // Optional: true to paint debug style UI, false otherwise
  );

Plain Text Editor

Display an editor that only shows plain text styling, and displays placeholder boxes for all non-paragraph nodes:

  final documentEditor = DocumentEditor(document: doc);

  return Editor.custom(
    editor: documentEditor,
    textStyleBuilder: (attributions) {
      // Force all text to look the same, regardless of attributions.
      return TextStyle(
        color: Colors.black,
        fontSize: 13,
        fontWeight: FontWeight.normal,
      );
    },
    componentBuilders: [
      (ComponentContext componentContext) {
        if (componentContext.currentNode is ParagraphNode) {
          return paragraphBuilder(componentContext);
        } else {
          // Display a placeholder box for all nodes other than
          // ParagraphNodes
          return UnknownComponent();
        }
      }
    ],
    showDebugPaint: showDebugPaint,
  );

Dark Theme Editor

Display an editor in dark mode with a custom font:

  final documentEditor = DocumentEditor(document: doc);

  return Editor.custom(
    editor: documentEditor,
    textStyleBuilder: (attributions) {
      // Make the text white and use a custom GoogleFont.
      final style = defaultStyleBuilder(attributions);
      return style.copyWith(
        color: Colors.white,
        fontFamily: GoogleFonts.merriweather().fontFamily,
        height: 1.8,
      );
    },
    // Make the selection color yellow to contrast with dark background.
    selectionStyle: SelectionStyle(
      textCaretColor: Colors.yellow,
      selectionColor: Colors.yellow.withOpacity(0.3),
    ),
    componentBuilders: [
      // Replace the regular horizontal rule with a light green one.
      (ComponentContext componentContext) {
        if (componentContext.currentNode is! HorizontalRuleNode) {
          return null;
        }
        final standardHr = horizontalRuleBuilder(componentContext) as HorizontalRuleComponent;

        return HorizontalRuleComponent(
          componentKey: standardHr.componentKey,
          color: Colors.lightGreenAccent,
          isSelected: standardHr.isSelected,
          selectionColor: standardHr.selectionColor,
        );
      },
      // Customize unordered list items to show an icon instead of a leading dot.
      (ComponentContext componentContext) {
        if (componentContext.currentNode is! ListItemNode ||
            (componentContext.currentNode as ListItemNode).type != ListItemType.unordered) {
          return null;
        }
        final standardUl = unorderedListItemBuilder(componentContext) as UnorderedListItemComponent;

        return UnorderedListItemComponent(
          textKey: componentContext.componentKey,
          text: standardUl.text,
          styleBuilder: standardUl.styleBuilder,
          dotBuilder: (context, component) {
            return Align(
              alignment: Alignment.centerRight,
              child: Padding(
                padding: const EdgeInsets.only(right: 10),
                child: Icon(
                  Icons.opacity,
                  size: 12,
                  color: component.styleBuilder({}).color,
                ),
              ),
            );
          },
          indent: standardUl.indent,
          textSelection: standardUl.textSelection,
          selectionColor: standardUl.selectionColor,
          hasCaret: standardUl.hasCaret,
          caretColor: standardUl.caretColor,
          showDebugPaint: standardUl.showDebugPaint,
        );
      },
      ...defaultComponentBuilders,
    ],
    showDebugPaint: showDebugPaint,
  );