使用角形材料自动完成

时间:2018-07-21 18:34:57

标签: angular rxjs6 angular-material-5

我需要一些有关使用角形材料的自动完成字段的帮助。首先,页面加载时,我有一个服务,可向后端节点应用程序进行API调用,该后端节点应用程序将请求发送至sanbox api。此电话会列出支持的城市。然后,它输入具有表单的城市列表组件。当用户输入内容时,我想将城市范围缩小到自动填写框内。到目前为止,我已经设置了一个新变量作为主题,并使用.filter()和.include()方法来过滤数组并将其返回给我的主题变量。返回值是订阅变量的对象形式,但是现在在模板上,我无法使用返回值来缩小结果范围。我知道它是因为我需要将结果返回到数组中。有人可以帮我概念化这一点吗(目前,我可以使用过滤器来缩小结果范围,但是在删除值之后,数组不会重新加载值)

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>

1 个答案:

答案 0 :(得分:0)

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>