Я пытаюсь использовать компонент ngx-mat-select-search, чтобы поместить в моем приложении раскрывающееся меню стиля mat-select с панелью поиска.
https://www.npmjs.com/package/ngx-mat-select-search
У меня выпадающий список работает нормально, но я пытаюсь превратить его в пользовательскую директиву, которую я затем могу вызывать и повторно использовать на нескольких страницах через приложение.
Пока у меня есть это: site-dropdown-component.ts
import {AfterViewInit, Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {FormControl} from '@angular/forms';
import {ReplaySubject, Subject} from 'rxjs';
import {MatSelect} from '@angular/material';
import {take, takeUntil} from 'rxjs/operators';
@Component({
selector: 'app-site-dropdown',
template: `
<mat-form-field class="w-100">
<mat-select [formControl]="siteCtrl" placeholder="Site" #singleSelect>
<mat-option>
<ngx-mat-select-search [formControl]="siteFilterCtrl" [placeholderLabel]="'Search Sites...'"></ngx-mat-select-search>
</mat-option>
<mat-option *ngFor="let site of filteredSites | async" [value]="site">{{site.name}}</mat-option>
</mat-select>
</mat-form-field>
`
})
export class SiteDropdownComponent implements OnInit, OnDestroy, AfterViewInit {
/** list of sites */
protected sites: Site[] = SITES;
/** control for the selected site */
public siteCtrl: FormControl = new FormControl();
/** control for the MatSelect filter keyword */
public siteFilterCtrl: FormControl = new FormControl();
/** list of sites filtered by search keyword */
public filteredSites: ReplaySubject<Site[]> = new ReplaySubject<Site[]>(1);
@ViewChild('singleSelect') singleSelect: MatSelect;
/** Subject that emits when the component has been destroyed. */
protected onDestroy = new Subject<void>();
constructor() { }
ngOnInit(): void {
// set initial selection
this.siteCtrl.setValue(this.sites);
// load the initial site list
this.filteredSites.next(this.sites.slice());
// listen for search field value changes
this.siteFilterCtrl.valueChanges
.pipe(takeUntil(this.onDestroy))
.subscribe(() => {
this.filterSites();
});
}
ngAfterViewInit(): void {
this.setInitialValue();
}
ngOnDestroy(): void {
this.onDestroy.next();
this.onDestroy.complete();
}
/**
* Sets the initial value after the filteredBanks are loaded initially
*/
protected setInitialValue() {
this.filteredSites
.pipe(take(1), takeUntil(this.onDestroy))
.subscribe(() => {
// setting the compareWith property to a comparison function
// triggers initializing the selection according to the initial value of
// the form control (i.e. _initializeSelection())
// this needs to be done after the filteredBanks are loaded initially
// and after the mat-option elements are available
this.singleSelect.compareWith = (a: Site, b: Site) => a && b && a.id === b.id;
});
}
protected filterSites() {
if (!this.sites) {
return;
}
// get the search keyword
let search = this.siteFilterCtrl.value;
if (!search) {
this.filteredSites.next(this.sites.slice());
return;
} else {
search = search.toLowerCase();
}
// filter the sites
this.filteredSites.next(
this.sites.filter(site => site.name.toLowerCase().indexOf(search) > -1)
);
}
}
export interface Site {
id: string;
name: string;
}
export const SITES: Site[] = [
{id: 'site1', name: 'Site 1'},
{id: 'site2', name: 'Site 2'},
{id: 'site3', name: 'Site 3'},
];
Для компонента, в котором я пытаюсь его использовать, у меня есть:
<app-site-dropdown formControlName="site"></app-site-dropdown>
А внутри класса компонентов у меня есть форма:
this.mySearchForm = this.formBuilder.group( {
site: []
});
Я могу видеть выпадающий список и взаимодействовать с ним очень хорошо, но когда я отправляю свою форму, я не могу получить значение выбранного параметра. Просто всегда возвращается null
, когда я пытаюсь mySearchForm.controls['site'].value
Чего мне не хватает, чтобы иметь возможность добавить свой пользовательский выпадающий компонент и получить его значение при отправке формы?
UPDATE:
Мне удалось заставить его работать, выполнив следующие действия:
Внутри site-dropdown.component.ts
, я изменил
protected siteCtrl: FormControl;
до
@Input() siteCtrl: FormControl;
И внутри моего html, используя пользовательский выпадающий список, я добавил:
<app-site-dropdown [siteCtrl]="myForm.get('site')"></app-site-dropdown>
Это позволило мне сохранить выбранное значение в моей форме при отправке.