Draft-js: Blocks removing

Created on 7 Mar 2016  ยท  7Comments  ยท  Source: facebook/draft-js

Is there any possibility to remove block completely instead of removing block's content and setting the block as "unstyled"?

In the TeX example blocks aren't removing completely:
https://github.com/facebook/draft-js/blob/master/examples%2Ftex%2Fjs%2Fmodifiers%2FremoveTeXBlock.js#L37

question

All 7 comments

Sure, you could use Modifier.removeRange.

I found it a little more intuitive to convert the ContentState into an array, remove the appropriate block, create a new ContentState using that altered array, and pushing that onto the EditorState. But I feel like there might be a hefty performance cost there?

Guess that depends on how big your document is, but I personally wouldn't worry too much about the performance aspect. The main reason I prefer using Modifier.removeRange is that I trust it to handle things correctly. If I were to create my own solution, I'd have to think about redo/undo, next selectionState, removing entities, etc. It's definitely possible, but I don't really see the gain here.

Ah, I actually didn't notice that it reset selectionState, didn't remove entities, etc โ€“ definitely good reasons to use Modifier!

I stumbled in here because I was trying to find the best way to remove an image / "atomic" block. It was a little more intuitive (and readable, code-wise) to think of these images as entire "blocks that needed deleting" โ€“ rather than "an entity over a range of characters that need to be selected and deleted". Dealing with everything on a block-level also simplified the code around deletions, since the Modifier route seems like it would require evaluating the surrounding blocks โ€“ something along the lines of:

if (this image is the only block) {
  simply remove all the characters in this block;
  return;
} 

if (this image is the first block) {
  create a selection state that starts at the beginning of the image block
  and ends at the beginning of the next block, and remove range forward;
} else if (this image is the last block) {
  create a selection state that starts at the end of the previous block
  and ends at the end of the image block, and remove range backward;
} else {
  create a selection state that starts at the end of the previous block
  and ends at the start of the next block and remove range in either direction;
}

But maybe (hopefully) there's a simpler way I'm missing? ๐Ÿ˜›

We've actually created our own atomic block type, which works a bit differently than the built in, so we can't use Modifier.removeRange for those. But I would assume that Draft handles removing atomic blocks as well in Modifier.removeRange if you e.g. pass the current selectionState as argument, no?

Yep, pretty sure Modifier.removeRange wipes out atomic blocks successfully. But I realized something important that I forgot to mention earlier โ€“ in our use case, we're actually hoping to remove an image not within our current selectionState.

Example: say we have two blocks โ€“ the first is just a block with plain text and the second is a block that's a single image. The user's cursor is currently sitting somewhere within the text block but when they move their cursor and hover over the image block, a trash bin icon appears over the image โ€“ and when the user clicks it, we want to remove the entire second block.

In the ContentState / array method, the steps are simple (simply remove that second element in the array,) but that brings up the issues you mentioned earlier. It seems like Modifier.removeRangeis the way to go โ€“ it just seems to require a bit more care than expected. :p

If that _is_ the way to go, do you think it'd be worth me trying to get a PR together to bake that in, maybe something along the lines of AtomicBlockUtils.removeAtomicBlock()?

Oh I see. I agree it wasn't very intuitive to work with selectionStates for those kinds of things at first. But now that I've worked with it for a while, I actually think it gives me another level of control. I also find it quite easy to reason about:

In order to create the correct selectionState for a deletion (i.e. anchorKey, focusKey, anchorOffset, focusOffset, isBackward), I can just imagine how I would normally select things using the mouse (or keyboard) before deleting them. I'm willing to bet almost everyone intuitively knows how that works and what the end result will be.

E.g. if I want to completely remove a line of text (or block in the case of draft) when writing, I would actually start by putting my cursor on either the next line's start, and select upwards (or backwards) to include the "target line". I could also do it the other way around, i.e. start by putting my cursor on the end of the line above, and select downwards to include the target line. Yet another way is to put the cursor on the start of the target line and press shift+โ†“. This will actually put the focus on the start of the next line.

Pressing backspace on any of the selections described above, would remove the target line without leaving a blank line behind. The only difference between them is where my cursor would end up afterwards.

Sorry if this got a bit long, and maybe a bit off topic. But having said all this, I think people would probably appreciate the helper method you described. Just know that you'd either have to include a lot of parameters, or make opinionated decisions. E.g. where would you put the cursor after deletion? Do you leave empty space behind or not?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

B-Reif picture B-Reif  ยท  3Comments

vierno picture vierno  ยท  3Comments

snaerth picture snaerth  ยท  3Comments

jackmatrix picture jackmatrix  ยท  3Comments

darklightblue picture darklightblue  ยท  3Comments