代码之家  ›  专栏  ›  技术社区  ›  Pari Baker

带自动完成功能的窗体生成器,角度为6

  •  1
  • Pari Baker  · 技术社区  · 6 年前

    我有两套代码可以用,但我都不能按我想要的方式工作。所以我希望有一些概念上的见解。

    我有一个从API获取服务的城市。此服务自动完成筛选结果。当我使用 form builder ,我无法获取要筛选的数据,因为它没有执行 fromLatestWith .

    我正在使用 从最近的 使用两个观测数据 valueChange 以及为城市带来的服务。它在我使用时起作用 formControl 但不能 formBuilder .

    当我不使用 弗拉斯特 我可以让服务和自动完成功能工作,但是,由于服务首先加载,所以我必须在自动完成下拉列表显示之前键入。

    理想情况下我想用 formbuilder 并拥有 自动完成下拉列表 初始化时。我错过了什么?

    以下是两个实例的副本:

    //using formBuilder with latestWith lets me see valueChange but doesnt
    //load cities if I don't use formBuilder and use formControl it works
    
    import { CityService } from "../services/city-list.service";
    import { Component, OnInit, OnDestroy } from "@angular/core";
    import { City } from "../models/city";
    import { Subscription, Observable } from "rxjs";
    import {
      map,
      filter,
      startWith,
      withLatestFrom,
      debounceTime
    } from "rxjs/operators";
    import {
      FormGroup,
      FormControl,
      FormBuilder,
      Validators,
      NgForm,
      Form
    } from "@angular/forms";
    
    @Component({
      selector: "app-city-list",
      templateUrl: "./city-list.component.html",
      styleUrls: ["./city-list.component.css"]
    })
    export class CityListComponent implements OnInit {
      cities: Observable<City[]>;
    
      destinationCitySub: Observable<City[]>;
      originCitySub: Observable<City[]>;
    
      instantFlightForm: FormGroup;
    
    
      constructor(public cityService: CityService, private fb: FormBuilder) {
    
      }
    
      ngOnInit() {
        this.instantFlightForm = this.fb.group({
          destinationCity: [""],
          originCity: ["", Validators.required],
          startDate: []
        });
    
    
    
        this.cityService.getCities();
        this.cities = this.cityService.getCityUpdateListener();
       this.destinationCitySub = this.valueChange('destinationCity');
    
      }
    
      private valueChange(string) {
        console.log(string);
        return this.instantFlightForm.get(string).valueChanges.pipe(
          withLatestFrom(this.cities),
          debounceTime(100),
          map(([term, city]) => {
            console.log(term);
            return this._filter(term, city);
          })
        );
      }
    
      private _filter(first, second): City[] {
        const filterValue = first.toLowerCase();
        return second.filter(option =>
          option.name.toLowerCase().includes(filterValue)
        );
      }
    
      onInstantSearch(form: FormGroup) {
        console.log(form.value);
      }
    }
    <mat-card>
    
      <form [formGroup]="instantFlightForm" (submit)="onInstantSearch(instantFlightForm)">
        <mat-form-field>
          <input  type="text" id="destinationCity" name="destinationCity" matInput formControlName="destinationCity" [matAutocomplete]="autoDestination">
    
          <mat-autocomplete #autoDestination="matAutocomplete">
            <mat-option *ngFor="let c of destinationCitySub|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 formControlName="originCity" [matAutocomplete]="autoOrigin">
    
        <mat-autocomplete #autoOrigin="matAutocomplete">
          <mat-option *ngFor="let c of originCitySub|async" [value]="c">
            {{c}}
          </mat-option>
        </mat-autocomplete>
      </mat-form-field>
      <mat-form-field>
          <input matInput id="startDate" name="startDate" formControlName="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>

    //using it without latestWith - lets me autocomplete but requires
    //typing first
    
    import { CityService } from "../services/city-list.service";
    import { Component, OnInit, OnDestroy } from "@angular/core";
    import { City } from "../models/city";
    import { Subscription, Observable } from "rxjs";
    import {
      map,
      filter,
      startWith,
      withLatestFrom,
      debounceTime
    } from "rxjs/operators";
    import {
      FormGroup,
      FormControl,
      FormBuilder,
      Validators,
      NgForm,
      Form
    } from "@angular/forms";
    
    @Component({
      selector: "app-city-list",
      templateUrl: "./city-list.component.html",
      styleUrls: ["./city-list.component.css"]
    })
    export class CityListComponent implements OnInit {
      cities: City[];
    citySub: Subscription;
      destinationCitySub: Observable<City[]>;
      originCitySub: Observable<City[]>;
    
      instantFlightForm: FormGroup;
    
      constructor(public cityService: CityService, private fb: FormBuilder) {
    
      }
    
      ngOnInit() {
        this.instantFlightForm = this.fb.group({
          destinationCity: [""],
          originCity: ["", Validators.required],
          startDate: []
        });
    
    
    
        this.cityService.getCities();
        this.citySub = this.cityService.getCityUpdateListener().subscribe(c=>this.cities=c);
       this.destinationCitySub = this.valueChange('destinationCity');
    
      }
    
      private valueChange(string) {
        return this.instantFlightForm.get(string).valueChanges.pipe(
         // withLatestFrom(this.cities),
          debounceTime(100),
          map((term) => {
            console.log(term);
            return this._filter(term);
          })
        );
      }
    
      private _filter(term): City[] {
        const filterValue = term.toLowerCase();
        return this.cities.filter(option =>
          option.name.toLowerCase().includes(filterValue)
        );
      }
    
      onInstantSearch(form: FormGroup) {
        console.log(form.value);
      }
    }
    1 回复  |  直到 6 年前
        1
  •  1
  •   bryan60    6 年前

    WithLatestFrom在可观测流上操作,而不是值。你需要将城市设置为可观测的,并确保它至少发射一次。

    this.cities = this.cityService.getCityUpdateListener();