facebookarchive / draft-js

A React framework for building text editors.
https://draftjs.org/
MIT License
22.58k stars 2.64k forks source link

.removeRange() does not clear the first Draft block #773

Open varunarora opened 8 years ago

varunarora commented 8 years ago

I think this is a bug, because this does not seem normal for any reason.

When the anchor edge of a selection which needs to be removed in code is the first block of the blockMap, it doesn't get removed from blockMap upon .removeRange(). In my case, there is an atomic block dangling as the first block (which could be unstyled too), but I don't see a reason why it should be there. My use case is one of repositioning sections on a document.

This behavior does not happen for when the range is anywhere else in the editor.

Code is pretty straightforward, nothing special needed to reproduce this:

...
// blocksToMove is an Array of ContentBlocks that constitute a section of the doc. Think of it as one header to the next header.
var startingKey = currentContent.getKeyBefore(fromKey);
var toMoveSelection = SelectionState.createEmpty(blocksToMove[blocksToMove.length - 1].get('key')).set( 'anchorKey', startingKey || fromKey);

// 'backward' doesn't help either.
var newContentState = Modifier.removeRange(
    currentContent, toMoveSelection, 'forward'
);
...

// Yes I know I could use const and lets.

When I observe the blockMap right after these operations, if starting key was for the first block, the block still remains in the map at the 0th (or first() position). Not the case when my range does not have the first block as its anchor.

Working with 0.5.0.

threescales commented 7 years ago

I have this question too.

hnordt commented 7 years ago

It happens for me too, but in my case, the block is not the first in the map, it's a empty block before an atomic block.

threescales commented 7 years ago

you can remove it ,but can't use removeRange()

export function removeBlockFromBlockMap(editorState: EditorState, blockKey: string) { var contentState = editorState.getCurrentContent(); var blockMap = contentState.getBlockMap(); var newBlockMap = blockMap.remove(blockKey) var newContentState = contentState.merge({ blockMap: newBlockMap }) as Draft.Model.ImmutableData.ContentState var newEditorState = EditorState.push(editorState, newContentState, 'remove-range') return newEditorState }

sophiebits commented 7 years ago

If you have

block ONE THIS IS block two

with the capitalized text highlighted, pressing backspace will delete the second block and change the first block's text to "block block two". I think this behavior makes sense.

If you change to highlight the entire first block, then we still merge the second block into the first, even though we end up taking none of the content from the first block. I'm open to taking a PR that special-cases this so if the selection begins with an entire block, we remove that block entirely rather than merging the trailing block's contents in. This would be a change to removeRangeFromContentState.