我当时正在考虑使用Angular Material自动完成模块,就像他们有一个示例here。 他们在概述中说,可以使用模板驱动的表单。所以我想我去试试。
模板:
<form (ngSubmit)="doSmth()" #f="ngForm">
<mat-form-field>
<input type="text" required id="name" (ngModel)="myControl" name="name" matInput [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let option of filteredOptions | async" [value]="option">{{ option }}</mat-option>
</mat-autocomplete>
</mat-form-field>
<button type="submit" [disabled]="!f.form.valid">Click</button>
</form>
组件:
@Component({
selector: 'autocomplete-filter-example',
templateUrl: 'autocomplete-filter-example.html',
styleUrls: ['autocomplete-filter-example.css'],
})
export class AutocompleteFilterExample implements OnInit {
myControl: FormControl();
options: string[] = ['One', 'Two', 'Three'];
filteredOptions: Observable<string[]>;
ngOnInit() {
this.filteredOptions = this.myControl.valueChanges
.pipe(
startWith(''),
map((value: string) => this.filter(value))
);
}
private filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.options.filter(option => option.toLowerCase().includes(filterValue));
}
}
问题是当我运行它时,出现错误:
AppComponent.html:1 ERROR TypeError: Cannot read property 'valueChanges' of undefined
所以我猜想ngModel在初始化之后被绑定了吗?或为什么这不起作用?我需要使用FormControl
的Sepaparte实例吗?
答案 0 :(得分:1)
如果要使用ngModel
和模板驱动的表单而不是表单控件,则可以将其与ngModelChange
一起使用。如果您随后要使用可观察对象或纯字符串数组,则由您决定。这是使用纯字符串数组:
<mat-form-field>
<input type="text" [ngModel]="myControl" name="name" matInput [matAutocomplete]="auto" (ngModelChange)="doFilter($event)" required>
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let option of filteredOptions" [value]="option">
{{ option }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
最初,我们可以为filteredOptions
赋予options
的值。让我们使用传播运算符在两个数组之间不创建引用:
options: string[] = ['One', 'Two', 'Three'];
filteredOptions = [... this.options];
myControl = '';
然后doFilter()
函数将如下所示:
doFilter(value) {
const filterValue = value.toLowerCase();
this.filteredOptions = this.options.filter(option => option.toLowerCase().includes(filterValue));
}
演示:StackBlitz
如果您不需要模板驱动的表单,则只需执行表单标签即可。
如前所述,如果您打算将来进行http请求以获取自动完成数据,那么您也可以使用可观察对象。如果在这一点上使用可观察到的东西已经可以更加明智,因为它很容易被替换。如果是这样,这是使用observables而不是字符串数组的选项:
import { Observable, of } from 'rxjs';
// ...
filteredOptions = of(this.options);
doFilter(value) {
const filterValue = value.toLowerCase();
this.filteredOptions = of(this.options.filter(option => option.toLowerCase().includes(filterValue)));
}
并在视图中使用异步管道:
<mat-option *ngFor="let option of filteredOptions | async" [value]="option">
演示:StackBlitz
答案 1 :(得分:0)
FormControl用于反应形式。您可以尝试以下代码。
myControl: any;
@ViewChild('f') ngForm: NgForm;
ngOnInit() {
this.subscription = this.ngForm.form.valueChanges.subscribe(x => {
console.log(x);
})
}
别忘了退订。另外,您可能需要使用[(ngModel)]而不是(ngModel)。