admin管理员组

文章数量:1293651

Reference Stackblitz for unusual behaviour.

I have a content editable div and an array of spans inside it using for loop as shown below.

<div
  [id]="parameterName()"
  contenteditable="true"
  class="expression-input"
  (input)="onInput($event)">

  @for (element of elements(); track $index) {
    @if (element.type == 'text') {
      <span>
        <span contenteditable="true" [id]="element.id" [class]="id">{{
          element.uiValue
        }}</span>
      </span>
    } @else if (element.type == 'expression') {
      <span contenteditable="false" [id]="element.id" class="expression">{{
        element.uiValue
      }}</span>
    }
  }
</div>

On component start there is one element in elements() array of type=='text'. Now when I type inside the empty content editable div. The content is coming of as a text node before span starts and not inside span. I am looking for the content I type to be placed inside span. So, in the onInput function I remove the text node and put the content of it inside the first element.uiValue as shown below.

  onInput($event: any) {
    const inputField = document.getElementById('subReddit');
    const childNodes = Array.from(inputField?.childNodes);
    let elementIdsUpdated = [];
    childNodes.forEach((node) => {
      const nodeId = (node as any).id;
      if (node.nodeType == Node.TEXT_NODE) {
        let elementIdUpdated: string;
        if (this.elements().length == 1) {
          this.elements.update((elements) => {
            elements[0].uiValue = node.textContent;
            elements[0].value = node.textContent;
            elements[0].id = elementIdUpdated = this.generateUniqueId();

            elementIdsUpdated.push(elementIdUpdated);
            return [...elements];
          });
        }
        inputField.removeChild(node);
        this.giveFocusToNodeAtPosition(elementIdUpdated);
      } else if (
        !elementIdsUpdated.includes(nodeId) &&
        this.elements().find((el) => el.id == (node as any).id)
      ) {
        this.elements.update((elements) => {
          const elementToUpdate = elements.find(
            (el) => el.id == (node as any).id
          );
          if (elementToUpdate) {
            elementToUpdate.value = node.textContent;
            elementToUpdate.uiValue = node.textContent;
            this.giveFocusToNodeAtPosition(elementToUpdate.id);
          }
          return [...elements];
        });
      }
    });
  }

The unusual part starts now. Let's say I type "Subreddit for Angular" and then remove the content I typed using Ctrl+A and backspace or just repeated keydowns of backspace key until the div is empty. Now when I type nothing shows up and the span element is not being rendered inside div event when there is one element inside elements() array. Even the Ctrl+V is not working inside div. What could be the Reason? How to fix it?

本文标签: angularUnusual Behaviour with content editable div and spanStack Overflow