Как я уже говорил в прошлом, я новичок в программировании и пытаюсь научить себя Angular - возможно, это приведет к новой карьере!Я создаю приложение для себя, чтобы справиться с веб-разработкой.В настоящее время я пытаюсь использовать автозаполнение материала в форме, чтобы, когда пользователь добавляет / вставляет значение в текстовый ввод, событие keyup также прослушивается в наблюдаемой, которая выполняет вызов API, который возвращает некоторые данные, и я использую возвращенную датузаполнить автозаполнение (у меня есть 3 на моей странице).Это моя HTML-форма ...
<form novalidate [formGroup]="assignmentForm">
<div>
<input type="text" matInput placeholder="User" formControlName="worker" name="worker" [matAutocomplete]="workerTemplate" #worker>
<mat-autocomplete #workerTemplate="matAutocomplete">
<mat-option *ngFor="let worker of workerTags" [value]="worker">{{ worker.displayName}}</mat-option>
</mat-autocomplete>
</div>
<div>
<input type="text" matInput placeholder="Company" formControlName="company" name="company" [matAutocomplete]="companyTemplate" #company>
<mat-autocomplete #companyTemplate="matAutocomplete">
<mat-option *ngFor="let company of companyTags" [value]="company">{{company.displayName}}</mat-option>
</mat-autocomplete>
</div>
<div>
<input type="text" matInput placeholder="Department" formControlName="department" name="department" [matAutocomplete]="departmentTemplate" #department>
<mat-autocomplete #departmentTemplate="matAutocomplete">
<mat-option *ngFor="let department of departmentTags" [value]="department">{{department.displayName}}</mat-option>
</mat-autocomplete>
</div>
</form>
Теперь в моем компоненте я использую Observable.merge для прослушивания всех трех входов, отсеиваюсь, чтобы пользователь не перегружал систему, я вызываю мой APIа затем выполните некоторую логику форматирования перед заполнением соответствующего массива данных для соответствующего автозаполнения.Вот мой код компонента (я уменьшил это для удобства чтения)
public companyTags: any[];
public departmentTags: any[];
public workerTags: any[];
@ViewChild('company')
private companyEl: ElementRef;
@ViewChild('department')
private departmentEl: ElementRef;
@ViewChild('worker')
private workerEl: ElementRef;
private assignmentSubscription: Subscription;
constructor(private apiService: ApiService) {}
public ngOnInit() {
const companySource = fromEvent(this.companyEl.nativeElement, 'keyup');
const departmentSource = fromEvent(this.departmentEl.nativeElement, 'keyup');
const workerSource = fromEvent(this.workerEl.nativeElement, 'keyup');
const tagsSource = merge(companySource, departmentSource, workerSource)
.pipe(
debounceTime(500),
distinctUntilChanged(),
flatMap((ev: KeyboardEvent) => {
// if the user presses backspace the value is "" and all results are returned (to set limit)
if ((<HTMLInputElement>ev.target).value !== '') {
return this.apiService.getTags((<HTMLInputElement>ev.target).name, (<HTMLInputElement>ev.target).value, 3)
}
return of([]);
}),
);
this.assignmentSubscription = tagsSource.subscribe((res) => {
this.clearAllTags();
if (res.length > 0) {
// the type is contained in the array so we can determine which array we need to populate
// we can use interpolation rather than a horrible if then else
this[`${res[0].type}Tags`] = res;
}
});
}
public clearAllTags(): void {
this.companyTags = null;
this.departmentTags = null;
this.workerTags = null;
}
Это все работает, но мне интересно, если это самый эффективный способ сделать это?Я немного читал о flatMap, mergeMaop и concatMap, и я не уверен, какой метод лучше всего использовать в моем случае?Также я должен поместить логику, содержащуюся в flatMap где-то еще, так как кажется, что это не то место?Я не уверен, как бы я это сделал, используя chaing или добавив другой метод в канал (.do?).Любые советы и мысли будут оценены.Если я не вижу смысла или плохо формулирую свой вопрос, пожалуйста, укажите это, и я перепишу / отредактирую.Большое спасибо заранее.