gpt4 book ai didi

javascript - Angular ngx-mat-select-search 自定义组件

转载 作者:搜寻专家 更新时间:2023-10-30 21:33:06 25 4
gpt4 key购买 nike

我正在尝试使用 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: []
});

我可以很好地查看下拉菜单并与之交互,但是当我提交表单时,我无法获取所选选项的值。当我尝试 mySearchForm.controls['site'].value

时,它总是返回 null

我缺少什么才能注入(inject)我的自定义下拉组件,并在提交表单时检索它的值?

更新:

我能够通过执行以下操作使其工作:

site-dropdown.component.ts 中,我更改了

protected siteCtrl: FormControl;

@Input() siteCtrl: FormControl;

在我使用自定义下拉菜单的 html 中,我添加了:

<app-site-dropdown [siteCtrl]="myForm.get('site')"></app-site-dropdown>

这使我能够在提交时将选定的值保存到我的表单中。

最佳答案

您可以通过 SiteDropdownComponent 获取所选选项的值实现 ControlValueAccessor界面如下,导致你的SiteDropdownComponent充当表单控件并允许使用例如访问值<app-site-dropdown formControlName="site"></app-site-dropdown> :

...
import { forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
selector: 'app-site-dropdown',
template: ...
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => SiteDropdownComponent),
multi: true
}
],
})
export class SiteDropdownComponent implements OnInit, OnDestroy, AfterViewInit, ControlValueAccessor {
...

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

constructor() { }

ngOnInit() {
...
// call this.onChange to notify the parent component that the value has changed
this.siteCtrl.valueChanges
.pipe(takeUntil(this.onDestroy))
.subscribe(value => this.onChange(value))
}

writeValue(value: string) {
// set the value of siteCtrl when the value is set from outside the component
this.siteCtrl.setValue(value);
}

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

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

}

参见例如https://github.com/bithost-gmbh/ngx-mat-select-search/blob/d7ea78d511bbec45143c58c855f013a44d0d5055/src/app/mat-select-search/mat-select-search.component.ts#L134

关于javascript - Angular ngx-mat-select-search 自定义组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56535536/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com