i want to use the equivalent of surroundContents() in angular with renderer2
having the caret in a certain position in a contenteditable div i want onClick() to wrap the previous charater in a span (I'm assuming that on click the caret position is not changing with preventdefault)
onChaining(event) {
const caretPosition = window.getSelection().getRangeAt(0);
const range = document.createRange();
range.setStart(caretPosition.commonAncestorContainer, caretPosition.startOffset - 1);
range.setEnd(caretPosition.commonAncestorContainer, caretPosition.endOffset );
const wrap= this.renderer.createElement('span');
range.surroundContents(wrap);
}
i want to use renderer2 instead of surroundContents and have that new dom reference so that i can roll back and delete the wrap if needed.
The position of the caret is not known (in a text node) so no previous reference exists.
Well it seems Renderer2
expects parent objects to have method appendChild()
. So you cannot use something like this.renderer.appendChild(range,wrap)
and same with insertBefore
. But still it is possible to achieve an undoable behavior. According the documentation surrondContents
:
This method is nearly equivalent to
newNode.appendChild(range.extractContents());
range.insertNode(newNode);
So we repeat the mentioned behavior and will keep the range and a clone of a selected text node.
changes: {
range: Range;content: Node
}[] = [];
render() {
const caretPosition = window.getSelection().getRangeAt(0);
const range = document.createRange();
range.setStart(
caretPosition.commonAncestorContainer,
caretPosition.startOffset - 1
);
range.setEnd(
caretPosition.commonAncestorContainer,
caretPosition.endOffset
);
const wrap = this.renderer.createElement("span");
this.renderer.setStyle(wrap, "background-color", "red");
const contents = range.extractContents();
this.changes.push({
range: range,
content: contents.cloneNode(true)
});
this.renderer.appendChild(wrap, contents);
range.insertNode(wrap);
}
undo() {
const action = this.changes.pop();
const range = action.range;
const node = range.extractContents();
range.insertNode(action.content);
}
And here is the Stackblitz sample