“angular-如何从文本区域获取已删除的文本”

huangapple go评论56阅读模式
英文:

angular- How to get the deleted text from textarea

问题

在Angular中,用户可以从输入框或文本区域字段中删除字符或单词的方式有几种:

  1. 按下退格键:当用户按下退格键时,它会删除光标前面的字符。

  2. 按下删除键:当用户按下删除键时,它会删除光标后面的字符。

  3. 选择并替换文本:用户可以选择输入框或文本区域字段中的一部分文本,并通过键入新字符来替换它。这有效地删除了所选文本。

  4. 剪切文本:用户可以使用剪切命令(Ctrl+X或Command+X)剪切文本的一部分。这会删除所选文本并将其复制到剪贴板。

  5. 清除整个字段:用户可以通过按Ctrl+A(或Command+A)选择所有文本,然后按删除键或退格键来清除整个输入框或文本区域字段。

这些是在Angular中用户可以从输入框或文本区域字段中删除字符或单词的一些常见方式。确切的行为可能会因特定实现和所使用的平台/浏览器而有所不同。

我需要一个函数来执行所有这些功能,以获取从文本区域中删除的文本。
该函数必须提供已删除的字符以及从中删除字符的单词,甚至如果整个单词被删除也要提供。

我被卡住了,不知道如何从文本区域中获取已删除的字符。我允许用户使用@键提到用户。如果用户删除了提到的单词中的任何字符,那么它必须删除整个单词。

英文:

In Angular, there are several ways a user can delete a character or word from an input or textarea field:

  1. Pressing the Backspace key: When the user presses the Backspace key, it deletes the character preceding the cursor.

  2. Pressing the Delete key: When the user presses the Delete key, it deletes the character following the cursor.

  3. Selecting and replacing text: The user can select a portion of the text in the input or textarea field and replace it by typing new characters. This effectively deletes the selected text.

  4. Cutting text: The user can cut a portion of the text by using the Cut command (Ctrl+X or Command+X). This removes the selected text and copies it to the clipboard.

  5. Clearing the entire field: The user can clear the entire input or textarea field by pressing Ctrl+A (or Command+A) to select all the text and then pressing the Delete key or Backspace key.

These are some of the common ways a user can delete characters or words from an input or textarea field in Angular. The exact behavior may vary depending on the specific implementation and the platform/browser being used.

I need a function to performs all these functions to get the deleted text from textarea.
The funciont(s) must give the character deleted and the word from which the character is deleted or even if the entire word is deleted.

I am stucked how to get the character deleted from textarea. I am allowing users to mention users using @ key.
If user deleted any character from the mentioned word then it must delete the entire word.

答案1

得分: 1

以下是您请求的代码部分的中文翻译:

  1. 将文本区域的值绑定到模型并监听文本区域内容的更改,但要为元素添加keydownkeyuppaste事件:

    <textarea
      [(ngModel)]="textAreaContent"
      (keydown)="captureBeforeChange($event)"
      (keyup)="captureAfterChange($event)"
      (paste)="handlePaste($event)"
      rows="4"
      cols="50"
    ></textarea>
    

    这样,您将能够轻松访问文本区域的先前值和当前(新)值。与paste绑定的方法仅会更改在其他方法中使用的变量的值,因此您可以轻松将其更改为(paste)="pasteUsed=true",尽管我更喜欢将所有逻辑和计算从模板中移到ts文件中。

  2. captureBeforeChange方法只会确保在任何更改之前更新您的先前文本值,因此它只包含this.previousContent = this.textAreaContent;

  3. 除此之外,所有逻辑都按以下方式组织:

  4. 区分由粘贴新内容引起的更改与由按删除键或退格键引起的更改;通过在使用时将handlePaste设置为true并在输入字段上的动作不使用粘贴时将其设置为false来完成此操作。

  5. 当内容发生更改时,区分是仅删除一个字符(按删除键或退格键)引起的更改,还是选择多个(多于1个)字符并在其上键入的更改。

  6. 无论删除/替换的字符长度如何,始终检查是否实际更改了以@开头的单词(提及),如果是,则删除整个单词。

  7. 如果内容是通过粘贴新内容更改的(在先前内容不等于粘贴后创建的新内容的任何情况下),则获取替换的内容并创建一个提及(@单词)的集合(数组)。

如果您需要代码的详细解释,请随时提问,我将编辑此回答以包括详细解释。

英文:

Even if I do asked for a specific case in that previous comment (about pasted content), here's what you can certainly do:

  1. Bind textarea value to a model and listen for changes of the content of textarea, but adding keydown, keyup and paste to the element:

    &lt;textarea
      [(ngModel)]=&quot;textAreaContent&quot;
      (keydown)=&quot;captureBeforeChange($event)&quot;
      (keyup)=&quot;captureAfterChange($event)&quot;
      (paste)=&quot;handlePaste($event)&quot;
      rows=&quot;4&quot;
      cols=&quot;50&quot;
    &gt;&lt;/textarea&gt;
    

This way you will make it easy to always access the previous value of the textarea and the current (new) value. Method bound to paste will only change the value of a var that's used in other methods, though, so you can easily change it to (paste)=&quot;pasteUsed=true&quot;, although I prefer removing all logic and calculations from template into ts file.

  1. captureBeforeChange method will just make sure you have your previous text value updated before any change, so it'll only have this.previousContent = this.textAreaContent;.

  2. Other than that, all logic is organized in this way:

  3. discern changes made by pasting new content from changes that are caused by hitting delete or backspace; this is done by setting th handlePaste to true when it's used and setting it to false when the action on input field is not using paste,

  4. when content is changed, discern when the change is caused by just one character (hitting delete or backspace) or if it's from selecting several (more than 1) characters and typing over them,

  5. whatever the length of the deleted/replaced characters is, always check if it's actually changing the word starting with @ (a mention) and remove the whole word if it is,

  6. if the content was changed by pasting new content (in any situation when previous content is not equal to the new one created after pasting) get the replaced content and also make a collection (an array) of mentions (@ words) that were replaced by the paste.

If you need detailed explanation of the code, don't hesitate to ask and I will edit this answer to include it.

Stackblitz example.

Whole ts code:

import { Component } from &#39;@angular/core&#39;;

@Component({
  selector: &#39;my-app&#39;,
  templateUrl: &#39;./app.component.html&#39;,
  styleUrls: [&#39;./app.component.css&#39;],
})
export class AppComponent {
  textAreaContent: string = &#39;&#39;;
  previousContent: string = &#39;&#39;;
  pasteUsed: boolean = false;
  mentionDeleted: boolean = false;

  constructor() {}

  ngOnInit(): void {}

  captureBeforeChange(event) {
    this.pasteUsed = false;
    // Capture the textarea content before the keypress
    this.previousContent = this.textAreaContent;
  }

  handlePaste(event: ClipboardEvent) {
    this.pasteUsed = true;
  }

  captureAfterChange(event) {
    // if content was changed with pressing backspace or delete keys, or if selection is made and typed over
    if (!this.pasteUsed) {
      // Compare the previous content with the current content to find the deletion
      let previousLength = this.previousContent.length;
      let newLength = this.textAreaContent.length;

      // triggered only if at least one character was removed
      if (this.previousContent.length &gt; this.textAreaContent.length) {
        // get starting index of a difference between previous and current content
        let diffIndex = this.findDifferenceIndex(
          this.previousContent,
          this.textAreaContent
        );
        // first scenario: only a single character deleted:
        if (previousLength == newLength + 1) {
          // check if mention (@) word should be deleted
          this.checkForMention(diffIndex);
          // check if the content to delete is not a mention
          if (!this.mentionDeleted) {
            let deletedChar = this.previousContent[diffIndex];
            console.log(&#39;Deleted character: &#39;, deletedChar);
          }
        }
        // second scenario: only a single character deleted:
        if (previousLength &gt; newLength + 1) {
          // check if mention (@) word should be deleted
          this.checkForMention(diffIndex);
          // check if the content to delete is not a mention
          if (!this.mentionDeleted) {
            let deletedContent = this.getDeletedSubstring();
            console.log(&#39;Deleted substring: &#39;, deletedContent);
          }
        }
      }
    }
    // if content was changed with paste, over whole content or over a selection
    else {
      // if content was actually changed
      if (this.previousContent != this.textAreaContent) {
        let deletedContent = this.getDeletedSubstring();
        console.log(&#39;Deleted substring by paste: &#39;, deletedContent);
        // if the paste deleted some mentions, get them all into an array of mentions
        if (deletedContent.includes(&#39;@&#39;)) {
          let deletedMentions = deletedContent.match(/@\w+/g);
          console.log(&#39;Deleted mentions by pate: &#39;, deletedMentions);
        } else {
        }
      }
    }
  }

  getDeletedSubstring() {
    return this.findDeletedSubstring(
      this.previousContent,
      this.textAreaContent
    );
  }

  checkForMention(diffIndex) {
    this.mentionDeleted = false;
    // get the whole word from which a character has been deleted
    let deletedWord = this.getDeletedWord(this.previousContent, diffIndex);
    // Check if the deleted character was part of a mention, if so, delete the whole word that includes the mention
    if (deletedWord.includes(&#39;@&#39;)) {
      this.textAreaContent = this.previousContent.replace(
        deletedWord + &#39; &#39;,
        &#39;&#39;
      );
      this.mentionDeleted = true;
      console.log(&#39;Deleted @ word: &#39;, deletedWord);
    }
  }

  findDeletedSubstring(previous, current) {
    var start = 0;
    var end = 0;

    // Find the start of the difference
    while (previous[start] === current[start]) {
      start++;
    }

    // Find the end of the difference
    while (
      previous[previous.length - 1 - end] === current[current.length - 1 - end]
    ) {
      end++;
    }

    // Return the deleted substring
    return previous.slice(start, previous.length - end);
  }

  findDifferenceIndex(previousContent, currentContent) {
    // Find the first index where the two strings differ
    let i = 0;
    while (previousContent[i] === currentContent[i]) {
      i++;
    }
    return i;
  }

  getDeletedWord(previousContent, diffIndex) {
    // Get the word that includes the character at the difference index
    let words = previousContent.split(&#39; &#39;);
    for (let word of words) {
      if (
        previousContent.indexOf(word) &lt;= diffIndex &amp;&amp;
        diffIndex &lt;= previousContent.indexOf(word) + word.length
      ) {
        return word;
      }
    }
  }
}

huangapple
  • 本文由 发表于 2023年6月5日 02:54:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76401980.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定