Angular Material,Mat Chips自动完成错误,在optionSelected之前执行matChipInputTokenEnd

Angular Material, Mat Chips Autocomplete Bug, matChipInputTokenEnd executed before optionSelected

在输入中键入一些文本并通过按Enter键从自动完成功能中选择一个选项时,两个字符串都保存为筹码。 图片在这里

但是,使用鼠标从自动完成功能中选择一个选项时,不会发生这种情况。

在Angular Material Autocomplete Chips上提供的示例中,在所述情况下,首先触发optionSelected,而在本地计算机上的同一代码中,它在matChipInputTokenEnd之后执行,从而导致错误。

有没有人遇到这个问题?


关于选择事件,当您按ENTER键时,将触发输入中的matChipInputTokenEnd和mat-autocomplete中的optionSelected。通常,这会首先使用optionSelected发生,因此当输入事件触发时,芯片将已经添加,而输入将没有值可添加。这就是为什么用鼠标单击不会出现此问题的原因,因为只会触发optionSelected事件。

现在,我通常说是因为在模块导入的组件上也遇到了这个问题。如果是这种情况,则可能是一个错误。

但是,我确实找到了快速解决方案。我所做的是检查mat-autocomplete对话框是否打开,并防止mat-chip-input添加新元素。也可以检查选项列表中的选定项目,但是性能较差,而不是我想要的行为。

希望这可以帮助:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@ViewChild('chipAutocomplete') chipAutocomplete: MatAutocomplete;

addElement(event: MatChipInputEvent) {
  if ((event.value || '').trim() && !this.chipAutocomplete.isOpen) {
    this.value.push({
      name: event.value.trim()
    });
  }

  if (event.input) {
    event.input.value = '';
  }

  this.chipInputControl.setValue(null);
}


我结合了@ama和其他答案,以获得我认为您正在描述的功能。关键是结合使用optionActivated全局变量和手动关闭自动完成面板:

  • optionActivated添加到您的mat-autocomplete
  • 1
    2
    3
    <input #autoInput (matChipInputTokenEnd)="inputTokenEnd($event)" ... >
    <mat-autocomplete (optionActivated)="optionActivated($event)"
                      (optionSelected)="optionSelected($event)... >

  • 添加optionActivated函数和全局变量
  • 1
    2
    3
    4
    5
    6
    7
    autocompleteTagsOptionActivated = false;

      optionActivated(event: MatAutocompleteActivatedEvent) {
        if (event.option) {
          this.autocompleteTagsOptionActivated = true;
        }
      }
  • 为输入的MatAutocompleteTrigger添加访问器
  • 1
    @ViewChild('autoInput', { read: MatAutocompleteTrigger }) matAutocompleteTrigger: MatAutocompleteTrigger;
  • inputTokenEnd更改为仅在未激活标签的情况下处理输入,并有条件地关闭自动完成功能
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
      inputTokenEnd(event: MatChipInputEvent): void {
        const input = event.input;
        const value = event.value;

        if ((value || '').trim() && !this.autocompleteTagsOptionActivated) {  
          this.value.push(value.trim());
        }

        // Reset the input value
        if (input) {
          input.value = '';
        }
        this.controlsForm.autocomplete.setValue(null);

        // If no autocomplete options were activated, then issue the command to close the panel.  The enter key that
        // triggers the input will inadventantly open the panel
        if (!this.autocompleteTagsOptionActivated) {
          this.matAutocompleteTrigger.closePanel()
        }
      }
  • 更改您的optionSelected以重置激活变量
  • 1
    2
    3
    4
    5
      optionSelected(event: MatAutocompleteSelectedEvent): void {
        this.autocompleteTagsOptionActivated = false;

        ...
      }

    尽管AndréDias提出的解决方案在您有严格的选择选择时可以使用,但如果您需要在选择中添加一个子字符串(在自动完成中仅包含" javascript"的情况下可以考虑" java"),则无法使用。为此,您还可以将optionActivated事件与全局变量一起使用(这不能完全解决问题,如果使用鼠标选择,仍然会遇到问题)。下面举一个例子。
    html部分:

    1
    2
    3
    4
    5
    6
    7
    8
            <mat-autocomplete
              #auto="matAutocomplete"
              (optionActivated)="optionActivated($event)"
              (optionSelected)="selectedTag($event)">
              <mat-option *ngFor="let tag of filteredTags | async" [value]="tag">
                {{ tag }}
              </mat-option>
            </mat-autocomplete>

    组成部分:

    1
    2
    3
    4
    5
    6
    7
      autocompleteTagsOptionActivated = false;

      optionActivated($event: MatAutocompleteActivatedEvent) {
        if ($event.option) {
          this.autocompleteTagsOptionActivated = true;
        }
      }

    然后检查布尔变量并将其从键盘选择中实际添加时设置为false:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
      addTag(event: MatChipInputEvent): void {
        const input = event.input;
        const value = event.value;

        if ((value || '').trim()  && !this.autocompleteTagsOptionActivated) {
          this.formArrayTags.push(this.formBuilder.control(value.trim().toLowerCase()));
        }

        // Reset the input value
        if (input) {
          input.value = '';
        }

        this.tagsControl.setValue(null);
        this.formArrayTags.markAsDirty();
      }
    1
    2
    3
    4
    5
    6
      selectedTag(event: MatAutocompleteSelectedEvent): void {
        this.formArrayTags.push(this.formBuilder.control(event.option.viewValue));
        this.tagInput.nativeElement.value = '';
        this.tagsControl.setValue(null);
        this.autocompleteTagsOptionActivated = false;
      }

    对我来说很好。在这里,我附加了meterial.angular.io提供的示例链接

    https://stackblitz.com/angular/klblpljogjd?file=app%2Fchips-autocomplete-example.ts