Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rich Text example: 'select all' and 'delete' does not delete everything when there is a list #2500

Open
aleksblendwerk opened this issue Dec 14, 2018 · 9 comments

Comments

@aleksblendwerk
Copy link

aleksblendwerk commented Dec 14, 2018

Do you want to request a feature or report a bug?

A bug.

What's the current behavior?

On the current "Rich Text" example on https://www.slatejs.org/#/rich-text the following steps are causing an unexpected behavior:

  • Delete the default contents
  • Create a new unordered list
  • Press 'Enter'
  • Click on the 'unordered list' button again
  • Select all (with CTRL-A)
  • Press 'Delete'

The editor's contents are not entirely removed, instead the unordered list is kept and the cursor is still indented, without any list items.

0i2imaxy4c

What's the expected behavior?

The entire content should be deleted.

@dons20
Copy link

dons20 commented Feb 21, 2019

This bug still exists, and there doesn't seem to be an easy way to get around it either.

@adjourn
Copy link
Contributor

adjourn commented Feb 21, 2019

Possible duct tape fix (haven't tested it): enforce via schema that first element is paragraph (or other).

@dons20
Copy link

dons20 commented Feb 21, 2019

I'm working on an editor built similar to the rich text example, so I might test if the same issue occurs there and attempt a fix.

@dons20
Copy link

dons20 commented Feb 23, 2019

The same issue still occurs in mine. This is after replicating the steps twice. You'll notice there are still two blocks of type ordered list.
image

I've tried using editor.moveToRangeOfDocument().delete() which did work to an extent...I attached it to a button. After clicking once, it didn't seem to activate, but after the 2nd and 3rd clicks they worked. However, upon examining the document, it also seemed to delete the required child block node, essentially leaving the editor in an unusable state.

The most effective quick-fix to this problem is to add a button or command to reset the editor to a default value. That way if it bugs out, you can return the editor to a usable state.

@dons20
Copy link

dons20 commented Feb 25, 2019

One possible fix is to keep track of both Ctrl+A and Delete usages. If Delete is used after select all Ctrl+A then you can use setBlocks(DEFAULT_NODE) to have it prevent the stacking in the first place. It's not the most efficient fix as it might have some unintended behaviours in rare cases, but I can confirm that it does work with this particular rich text example (and perhaps other similar list implementations).

const DEFAULT_NODE = "paragraph";
const isDeleteHotKey = isKeyHotkey("delete");
const isSelectAllHotKey = isKeyHotkey("mod+a");

//using React hooks
function Editor() {
  const [isAllSelected, setAllSelected] = useState(false);
  ...

  const onKeyDown = (event, editor, next) => {
    ...
    } else if (isSelectAllHotKey(event)) {
      setAllSelected(!isAllSelected); //Toggle selected flag for Ctrl+A
      return next();
    } else if (isDeleteHotKey(event)) { 
      if (isAllSelected) {
        editor.setBlocks(DEFAULT_NODE);
        setAllSelected(false);
        return next();
      } else {
        return next();
      }
    } else {
       if (isAllSelected) setAllSelected(false); //Ensure isAllSelected is false on other key presses.
       return next();
    }
  }
}

@steida
Copy link

steida commented Mar 9, 2019

I had a similar issue and I fixed it with user-select: none.

const Uneditable: FunctionComponent = props => {
  return (
    <>
      <div contentEditable={false}>{props.children}</div>
      {/* 
        To fix errror: "IndexSizeError: Failed to execute 'getRangeAt'
        on 'Selection': 0 is not a valid index." and some others.
      */}
      <style jsx>{`
        div {
          user-select: none;
        }
      `}</style>
    </>
  );
};

@hanford
Copy link
Contributor

hanford commented Apr 1, 2020

Went down the same path as @dons20 - here is the updated code to work with Slate 0.50+

import { Transforms, .. } from 'slate';

..

const isSelectAllHotkey = isHotkey('mod+a');
const isDeleteHotkey = isHotkey('backspace');

..

const [isAllSelected, setAllSelected] = React.useState(false);

..


onKeyDown={event => {
  if (isDeleteHotkey(event)) {
    if (isAllSelected) {
      Transforms.delete(editor);
      Transforms.setNodes(editor, { type: 'paragraph' });
      setAllSelected(false);
      return;
    }
  }

  if (isSelectAllHotkey(event)) {
    setAllSelected(!isAllSelected);
  } else {
    setAllSelected(false);
  }

While not ideal, it fixed the bug for me 🤷‍♂️

@idanen
Copy link

idanen commented Feb 8, 2023

This reproduced for use when using tables.
Can reproduce here: https://www.slatejs.org/examples/tables

  1. delete everything after the table
  2. select all
  3. delete

Now we're always in a single td (without table, tr etc.) and trying to break out of it just adds more tds.

So to solve it we added this to the editor.insertBreak():

if (selection) {
    const [cell] = Editor.nodes(editor, {
        match: (n) => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'table-cell',
    });

    if (cell) {
        const [, cellPath] = cell;
        const start = Editor.start(editor, cellPath);
        const end = Editor.end(editor, cellPath);

        if (Point.equals(selection.anchor, end) || Point.equals(selection.anchor, start)) {
            Transforms.setNodes(editor, { type: 'container' });
        }
    }
}

insertBreak();

Hope this might help others

@kumarajay0412
Copy link

I used Transforms.select(editor, []) and it work fine for me

https://docs.slatejs.org/concepts/03-locations

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants