import { COMMA, ENTER } from '@angular/cdk/keycodes'; import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; import { UntypedFormControl } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatChipInputEvent } from '@angular/material/chips'; import { Tag } from '@app/core/model/tag/tag'; import { TagService } from '@app/core/services/tag/tag.service'; import { BaseComponent } from '@common/base/base.component'; import { QueryResult } from '@common/model/query-result'; import { Observable } from 'rxjs'; import { map, mergeMap, startWith } from 'rxjs/operators'; @Component({ selector: 'app-tags-field-component', templateUrl: 'tags-field.component.html', styleUrls: ['./tags-field.component.scss'] }) export class TagsComponent extends BaseComponent implements OnInit { @Input() form: UntypedFormControl = null; separatorKeysCodes: number[] = [ENTER, COMMA]; filteredTags: Observable; tags: string[] = []; @ViewChild('tagInput') tagInput: ElementRef; constructor( private tagService: TagService ) { super(); } ngOnInit(): void { this.tags = this.form.value || []; this.filteredTags = this.form.valueChanges.pipe( startWith(null), mergeMap((tag: string | null) => (this.tagService.query(this.tagService.buildAutocompleteLookup(tag)))), map((queryResult: QueryResult) => queryResult.items.map(x => x.label)), ); } add(event: MatChipInputEvent): void { if(this.form.disabled == true) return; const value = (event.value || '').trim(); // Add our tag if (value) { this.tags.push(value); } // Clear the input value event.chipInput!.clear(); this.form.setValue(this.tags); } remove(tag: string): void { if(this.form.disabled == true) return; const index = this.tags.indexOf(tag); if (index >= 0) { this.tags.splice(index, 1); } } selected(event: MatAutocompleteSelectedEvent): void { this.tags.push(event.option.viewValue); this.tagInput.nativeElement.value = ''; this.form.setValue(this.tags); } }