自动完成 angular 材料
Autocomplete with angular materials
我需要一些有关使用 angular 材料自动完成字段的帮助。首先,当页面加载时,我有一个服务对后端节点应用程序进行 API 调用,该应用程序将请求发送到 sanbox api。此调用带来了支持城市的列表。然后它提供具有表单的城市列表组件。当用户键入时,我想将城市缩小到一个自动完成框中。到目前为止,我已经将一个新变量设置为主题并使用 .filter() 和 .include() 方法来过滤数组并将其 return 到我的主题变量。 return 是我的订阅变量的对象形式,但现在在模板上我不能使用 returned 值来缩小我的结果。我认为这是因为我需要 return 我的结果到一个数组中。有人可以帮我概念化这个吗(目前我可以得到过滤器来缩小结果范围,但是数组在删除它们后不会重新加载值)
city-list Component.ts
import { CityService } from "./services/city-list.service";
import { Component, OnInit, OnDestroy } from "@angular/core";
import { City } from "../cities/models/city";
import { Subscription, Observable } from "rxjs";
import { map, startWith, debounceTime } from "rxjs/operators";
import {FormGroup, FormControl, Validators, NgForm} from '@angular/forms';
@Component({
selector: "<app-cities></app-cities>",
templateUrl: "./city-list.component.html"
})
export class CityListComponent implements OnInit, OnDestroy {
cities: City[];
private citiesSub: Subscription;
destinationCity: FormControl = new FormControl();
currentCity: Subscription;
filteredCities: City[];
constructor(public cityService: CityService) {}
ngOnInit() {
this.cityService.getCities();
this.citiesSub = this.cityService
.getCityUpdateListener()
.subscribe((cities) => {
this.cities = cities;
});
this.currentCity = this.destinationCity.valueChanges.pipe(
debounceTime(400),
startWith(''),
).subscribe(term=>{
if(!term){
return;
}
this._filter(term);
}
);
}
private _filter(value: string): City[] {
const filterValue = value.toLowerCase();
return this.filteredCities = this.cities.filter(option => option.name.toLocaleLowerCase().includes(filterValue));
}
ngOnDestroy() {
this.citiesSub.unsubscribe();
}
onSearch(form: NgForm){
console.log(form.value);
}
}
city service.ts
import { Subject } from 'rxjs';
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import { map } from "rxjs/operators";
import {City} from '../models/city';
@Injectable({ providedIn: "root" })
export class CityService {
cities: City[] = [];
private updatedCities = new Subject<City[]>();
constructor(private http: HttpClient) {}
getCities() {
this.http.get<{message: string; cities: City[]}>('http://localhost:3000/cities')
.pipe(
map((cityData)=>{
return cityData.cities.map(city=>{
return{
code: city.code,
name: city.name
};
});
})
)
.subscribe((transCity) => {
this.cities = transCity;
// console.log(this.cities);
this.updatedCities.next([...this.cities]);
});
}
getCityUpdateListener() {
return this.updatedCities.asObservable();
}
}
city-list.html
<mat-card>
<form #instantFlight="ngForm">
<mat-form-field>
<input type="text" id="destinationCity" name="destinationCity" matInput [formControl]="destinationCity" [matAutocomplete]="autoDestination">
<mat-autocomplete #autoDestination="matAutocomplete">
<mat-option *ngFor="let c of cities" [value]="c.code">
{{c.name}} - {{c.code}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<button mat-raised-button type="submit">Search</button>
</form>
</mat-card>
import { CityService } from "./services/city-list.service";
import { Component, OnInit, OnDestroy } from "@angular/core";
import { City } from "../cities/models/city";
import { Subscription, Observable } from "rxjs";
import { map, startWith, debounceTime } from "rxjs/operators";
import { FormGroup, FormControl, Validators, NgForm } from "@angular/forms";
@Component({
selector: "<app-cities></app-cities>",
templateUrl: "./city-list.component.html",
styleUrls: ["./cities-list.component.css"]
})
export class CityListComponent implements OnInit, OnDestroy {
cities: City[]=[];
private citiesSub: Subscription;
currentCity: Observable<City[]>;
destinationCity: FormControl = new FormControl();
originCity: FormControl = new FormControl();
startDate: FormControl = new FormControl();
constructor(public cityService: CityService) {}
ngOnInit() {
this.cityService.getCities();
this.citiesSub = this.cityService
.getCityUpdateListener()
.subscribe(cities => {
this.cities = cities;
});
this.currentCity = this.destinationCity.valueChanges
.pipe(
startWith(''),
debounceTime(10),
map(x=>{
return this._filter(x);
}
));
}
private _filter(value: string): City[]{
const filterValue = value.toLowerCase();
return(this.cities.filter(option => option.name.toLowerCase().includes(filterValue)));
}
ngOnDestroy() {
this.citiesSub.unsubscribe();
}
}
<mat-card>
<form (submit)="onLogin(instantFlight)" #instantFlight="ngForm">
<mat-form-field>
<input type="text" id="destinationCity" name="destinationCity" matInput [formControl]="destinationCity" [matAutocomplete]="autoDestination">
<mat-autocomplete #autoDestination="matAutocomplete">
<mat-option *ngFor="let c of currentCity | async" [value]="c.code">
{{c.name}} - {{c.code}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field>
<input type="text" id="originCity" name="originCity" matInput [formControl]="originCity" [matAutocomplete]="autoOrigin">
<mat-autocomplete #autoOrigin="matAutocomplete">
<mat-option *ngFor="let c of cities" [value]="c.code">
{{c.name}} - {{c.code}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field>
<input matInput id="startDate" name="startDate" [formControl]="startDate" [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
<button mat-raised-button type="submit" color="accent">Search</button>
</form>
</mat-card>
我需要一些有关使用 angular 材料自动完成字段的帮助。首先,当页面加载时,我有一个服务对后端节点应用程序进行 API 调用,该应用程序将请求发送到 sanbox api。此调用带来了支持城市的列表。然后它提供具有表单的城市列表组件。当用户键入时,我想将城市缩小到一个自动完成框中。到目前为止,我已经将一个新变量设置为主题并使用 .filter() 和 .include() 方法来过滤数组并将其 return 到我的主题变量。 return 是我的订阅变量的对象形式,但现在在模板上我不能使用 returned 值来缩小我的结果。我认为这是因为我需要 return 我的结果到一个数组中。有人可以帮我概念化这个吗(目前我可以得到过滤器来缩小结果范围,但是数组在删除它们后不会重新加载值)
city-list Component.ts
import { CityService } from "./services/city-list.service";
import { Component, OnInit, OnDestroy } from "@angular/core";
import { City } from "../cities/models/city";
import { Subscription, Observable } from "rxjs";
import { map, startWith, debounceTime } from "rxjs/operators";
import {FormGroup, FormControl, Validators, NgForm} from '@angular/forms';
@Component({
selector: "<app-cities></app-cities>",
templateUrl: "./city-list.component.html"
})
export class CityListComponent implements OnInit, OnDestroy {
cities: City[];
private citiesSub: Subscription;
destinationCity: FormControl = new FormControl();
currentCity: Subscription;
filteredCities: City[];
constructor(public cityService: CityService) {}
ngOnInit() {
this.cityService.getCities();
this.citiesSub = this.cityService
.getCityUpdateListener()
.subscribe((cities) => {
this.cities = cities;
});
this.currentCity = this.destinationCity.valueChanges.pipe(
debounceTime(400),
startWith(''),
).subscribe(term=>{
if(!term){
return;
}
this._filter(term);
}
);
}
private _filter(value: string): City[] {
const filterValue = value.toLowerCase();
return this.filteredCities = this.cities.filter(option => option.name.toLocaleLowerCase().includes(filterValue));
}
ngOnDestroy() {
this.citiesSub.unsubscribe();
}
onSearch(form: NgForm){
console.log(form.value);
}
}
city service.ts
import { Subject } from 'rxjs';
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import { map } from "rxjs/operators";
import {City} from '../models/city';
@Injectable({ providedIn: "root" })
export class CityService {
cities: City[] = [];
private updatedCities = new Subject<City[]>();
constructor(private http: HttpClient) {}
getCities() {
this.http.get<{message: string; cities: City[]}>('http://localhost:3000/cities')
.pipe(
map((cityData)=>{
return cityData.cities.map(city=>{
return{
code: city.code,
name: city.name
};
});
})
)
.subscribe((transCity) => {
this.cities = transCity;
// console.log(this.cities);
this.updatedCities.next([...this.cities]);
});
}
getCityUpdateListener() {
return this.updatedCities.asObservable();
}
}
city-list.html
<mat-card>
<form #instantFlight="ngForm">
<mat-form-field>
<input type="text" id="destinationCity" name="destinationCity" matInput [formControl]="destinationCity" [matAutocomplete]="autoDestination">
<mat-autocomplete #autoDestination="matAutocomplete">
<mat-option *ngFor="let c of cities" [value]="c.code">
{{c.name}} - {{c.code}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<button mat-raised-button type="submit">Search</button>
</form>
</mat-card>
import { CityService } from "./services/city-list.service";
import { Component, OnInit, OnDestroy } from "@angular/core";
import { City } from "../cities/models/city";
import { Subscription, Observable } from "rxjs";
import { map, startWith, debounceTime } from "rxjs/operators";
import { FormGroup, FormControl, Validators, NgForm } from "@angular/forms";
@Component({
selector: "<app-cities></app-cities>",
templateUrl: "./city-list.component.html",
styleUrls: ["./cities-list.component.css"]
})
export class CityListComponent implements OnInit, OnDestroy {
cities: City[]=[];
private citiesSub: Subscription;
currentCity: Observable<City[]>;
destinationCity: FormControl = new FormControl();
originCity: FormControl = new FormControl();
startDate: FormControl = new FormControl();
constructor(public cityService: CityService) {}
ngOnInit() {
this.cityService.getCities();
this.citiesSub = this.cityService
.getCityUpdateListener()
.subscribe(cities => {
this.cities = cities;
});
this.currentCity = this.destinationCity.valueChanges
.pipe(
startWith(''),
debounceTime(10),
map(x=>{
return this._filter(x);
}
));
}
private _filter(value: string): City[]{
const filterValue = value.toLowerCase();
return(this.cities.filter(option => option.name.toLowerCase().includes(filterValue)));
}
ngOnDestroy() {
this.citiesSub.unsubscribe();
}
}
<mat-card>
<form (submit)="onLogin(instantFlight)" #instantFlight="ngForm">
<mat-form-field>
<input type="text" id="destinationCity" name="destinationCity" matInput [formControl]="destinationCity" [matAutocomplete]="autoDestination">
<mat-autocomplete #autoDestination="matAutocomplete">
<mat-option *ngFor="let c of currentCity | async" [value]="c.code">
{{c.name}} - {{c.code}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field>
<input type="text" id="originCity" name="originCity" matInput [formControl]="originCity" [matAutocomplete]="autoOrigin">
<mat-autocomplete #autoOrigin="matAutocomplete">
<mat-option *ngFor="let c of cities" [value]="c.code">
{{c.name}} - {{c.code}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field>
<input matInput id="startDate" name="startDate" [formControl]="startDate" [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
<button mat-raised-button type="submit" color="accent">Search</button>
</form>
</mat-card>