Angular material Chips Autocomplete

Chips Autocomplete 官网的例子我没法正常使用,无法实现搜索

我的select是个通用组件,现在贴代码:

component.ts

javascript 复制代码
import {
  Component,
  ElementRef,
  forwardRef,
  Input,
  OnChanges,
  OnDestroy,
  OnInit,
  SimpleChanges,
  ViewChild,
} from '@angular/core';
import { Tag } from '../../models/tag/tag';
import { map, startWith, takeUntil } from 'rxjs/operators';
import { ControlValueAccessor, UntypedFormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { COMMA, ENTER } from '@angular/cdk/keycodes';
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
// import { MatChipInputEvent } from '@angular/material/chips';
import { TagService } from '../../services/tag/tag.service';
import { TagType } from '../../enums/TagType';
import { ISearchOptions } from '../../interfaces/SearchOptions';
import { SubscriberWrapperComponent } from '../subscriber-wrapper/subscriber-wrapper.component';

@Component({
  selector: 'app-tags-select',
  templateUrl: './tags-select.component.html',
  styleUrls: ['./tags-select.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => TagsSelectComponent),
      multi: true,
    },
  ],
})
export class TagsSelectComponent
  extends SubscriberWrapperComponent
  implements ControlValueAccessor, OnChanges, OnInit, OnDestroy
{
  @Input() title: string;
  @Input() disabled: boolean;
  @Input() color: 'primary' | 'accent' | 'warn';
  @Input() type: TagType;
  @Input() tags: Tag[];

  filteredTags: Tag[];
  selectedTags: Tag[] = [];
  separatorKeysCodes: number[] = [ENTER, COMMA];
  tagCtrl = new UntypedFormControl('');
  hideComponent: boolean;

  @ViewChild('tagInput') tagInput: ElementRef<HTMLInputElement>;
  @ViewChild('chipList') chipList: ElementRef;

  constructor(private tagService: TagService) {
    super();
  }

  onChange = (_: any) => {};
  onTouched = () => {};

  async ngOnInit() {
    this.initTags();
    const conditions = [];
    if (this.type) {
      conditions.push({
        key: 'type',
        value: this.type,
        operator: '=',
      });
    }
    this.tags = await this.listTags('', {
      conditions,
    });
    await this.updateFilterTags();
  }

  async listTags(query: string = '', options: ISearchOptions = {}) {
    if (!this.tags) {
      const response = await this.tagService.list(query, options);
      return response.entities;
    } else {
      return this.tags;
    }
  }

  // add(event: MatChipInputEvent): void {
  //   event.chipInput!.clear();

  //   this.tagCtrl.setValue(null);
  // }

  remove(tag: Tag): void {
    const index = this.selectedTags.indexOf(tag);
    if (index >= 0) {
      this.selectedTags.splice(index, 1);
    }
    this.filteredTags.push(tag);
    // this.onChange(this.selectedTags);  
  }

  selected(event: MatAutocompleteSelectedEvent): void {
    this.selectedTags.push(event.option.value);
    this.tagInput.nativeElement.value = '';
    this.tagCtrl.setValue(null);
    // this.onChange(this.selectedTags);
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  writeValue(selectedTags: Tag[] = []): void {
    this.selectedTags = selectedTags ?? [];
    this.updateFilterTags();
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.disabled?.currentValue) {
      this.tagCtrl.disable();
    }

    if (changes.tags?.currentValue) {
      this.updateFilterTags();
    }
  }

  initTags() {
    this.tagCtrl.valueChanges
      .pipe(
        takeUntil(this.unsubscribeAll),
        startWith(null),
        map(async (value?: string) => {
          await this.updateFilterTags(value);
        })
      )
      .subscribe();
  }

  async updateFilterTags(value?: string) {
    const conditions = [];
    if (this.type) {
      conditions.push({
        key: 'type',
        value: this.type,
        operator: '=',
      });
    }
    const response = value
    ? this.tags?.filter((tag: Tag) => {
        const regex = new RegExp(`^${value}`, 'i'); 
        return regex.test(tag.title?tag.title:'');
      }) || []
    : this.tags?.slice() || [];
    
    const selectedTagIds = this.selectedTags.map((tag: Tag) => tag.id);
    this.filteredTags = response.filter((tag: Tag) => !selectedTagIds.includes(tag.id));
  }
}

页面.html

html 复制代码
<mat-label>{{title}}</mat-label>
<mat-form-field class="tag-chip-list" *ngIf="!hideComponent">
  <mat-chip-list #chipList aria-label="Tag selection" [disabled]="disabled">
    <mat-chip [color]="color" [class]="color"
              *ngFor="let tag of selectedTags; let i=index"
              (removed)="remove(tag)">
      <button matChipRemove>
        <mat-icon svgIcon="CloseBlue" class="close-icon"></mat-icon>
      </button>
      {{tag.name}}
    </mat-chip>
    <input
      placeholder="Add another tag..."
      #tagInput
      [formControl]="tagCtrl"
      [matAutocomplete]="auto"
      [matChipInputFor]="chipList"
      [matChipInputSeparatorKeyCodes]="separatorKeysCodes">
  </mat-chip-list>
  <mat-autocomplete #auto="matAutocomplete"
                    (optionSelected)="selected($event)">
    <mat-option *ngFor="let tag of filteredTags" [value]="tag"
                [innerHTML]="tag.name">

    </mat-option>
  </mat-autocomplete>
</mat-form-field>
相关推荐
m0_7482561415 分钟前
前端 MYTED单篇TED词汇学习功能优化
前端·学习
小马哥编程1 小时前
Function.prototype和Object.prototype 的区别
javascript
小白学前端6661 小时前
React Router 深入指南:从入门到进阶
前端·react.js·react
web130933203982 小时前
前端下载后端文件流,文件可以下载,但是打不开,显示“文件已损坏”的问题分析与解决方案
前端
王小王和他的小伙伴2 小时前
解决 vue3 中 echarts图表在el-dialog中显示问题
javascript·vue.js·echarts
学前端的小朱2 小时前
处理字体图标、js、html及其他资源
开发语言·javascript·webpack·html·打包工具
outstanding木槿2 小时前
react+antd的Table组件编辑单元格
前端·javascript·react.js·前端框架
好名字08213 小时前
前端取Content-Disposition中的filename字段与解码(vue)
前端·javascript·vue.js·前端框架
摇光933 小时前
js高阶-async与事件循环
开发语言·javascript·事件循环·宏任务·微任务
隐形喷火龙3 小时前
element ui--下拉根据拼音首字母过滤
前端·vue.js·ui