1

I'm experimenting with lexical, and I have a specific use case I can't implement.

A user enters some text, the app sends it to a backend to check for mistakes. In response, the backend returns information about errors with specified position of a word which contains an error.

Now, I need to take these offsets and select a fragment of the text based on them.

For example. User entered text: "Hello worldd!" Got from backend info that I should highlight the worldd.

I have not found how to do it in lexical.

This is an example of what I have tried.

editor.update(() => {
  const rangeSelection = $createRangeSelection();

  rangeSelection.applyDOMRange({
    startContainer: editor.getRootElement(),
    endContainer: editor.getRootElement(),
    collapsed: false,
    startOffset: 6,
    endOffset: 12,
  });

  $setSelection(rangeSelection);
});

// Here I'm trying to get the current selection.
const selection = $getSelection();

// The text contains the entire text in editor, but not the text I selected at previous step
const text = selection.getTextContent();

1 Answer 1

0

I was also looking for a solution to your question. Sorry a bit late but here's my solution.

In the mock up below, I'm just moving the selection forwards by one character (both the anchor and focus) but of course you can do whatever you need to here in your use case. Remember these values are relative to the node in arguments 1 and 3.

I've tried to keep types explicit so you can find them easier in the docs.

import {
    $createRangeSelection,
    $createTextNode,
    $getSelection,
    $isRangeSelection,
    $setSelection,
    PointType,
} from "lexical";

const YourPlugin = () => {
    const [editor] = useLexicalComposerContext();

    const foo = (): boolean => {
        editor.update(() => {
            const currentSelection = $getSelection();

            // Just for this example, I'm moving the selection 
            // forward by 1 character but do whatever you need to do.
            const selectionOffset: number = 1;

            if ($isRangeSelection(currentSelection)) {
                const anchor: PointType | null = currentSelection.anchor;
                const focus: PointType | null = currentSelection.focus;

                const newNode = $createTextNode("Some new node");
                // ^^ This could also be an existing node - whatever 
                // applies to your app.
                $insertNodes([newNode])
                // ^^ How you insert the node is up to you. E.g. you 
                // might want to append it to an existing paragraph 
                // node like
                const parent = ...
                parent.append(newNode);

                const newSelection = $createRangeSelection();
                newSelection.setTextNodeRange(newNode, anchor.offset + selectionOffset, newNode, focus.offset + selectionOffset);
                $setSelection(newSelection);
            }
        });

        return true;
    };
}

export default YourPlugin

Hopefully that gives you something to go off. Also, if you need to check the selection after updating, remember that in general, Lexical functions with a $ prefixed to their name need to be called within editor.update(() => {}) or editorState.read(() => {}). I.e. you should be able to just move those lines up into the update callback.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.