繁体   English   中英

Angular2 级联下拉菜单与 Material Design 和 ReactiveForms

[英]Angular2 Cascading Dropdowns with Material Design and ReactiveForms

我正在使用 Material Design 和 ReactiveForms 使用级联下拉菜单。 该代码有一个州的下拉列表,一旦选择,将过滤一个城市的下拉列表。

我发现这个例子http://www.talkingdotnet.com/cascading-dropdown-select-list-using-angular-js-2/但它没有使用reactiveForms。

目前屏幕加载没有错误。 状态下拉列表有一个状态列表。 选择状态时会发生这种情况..../MainComponent 类 MainComponent 中的错误 - 内联模板:11:16 导致:无法读取未定义的属性“值”

这是状态的接口

export interface IState {
    state: string;
}

这是城市的界面

    export interface ICity {
    state: string;
    city: string;
}

这是城市的服务

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/distinct';
import 'rxjs/add/operator/catch';
import { ICity } from './city.interface'

@Injectable()
export class CityService {
  private _urlCity = '../../api/city.json';

  constructor(private _http: Http) { }

  getCity(stateName:string): Observable<ICity[]> {
    return this._http.get(this._urlCity)
      .map((response: Response) => <ICity[]>response.json())
      .catch(this.handleError);
  }

  private handleError(error: Response) {
    console.error('I found something bad');
    console.error(error);
    return Observable.throw(error.json().error || 'Server error ...');
  }


}

这是主要组件的 HTML

<div class="card-container">
  <md-card>
    <md-card-title>
      <h3>Testing Cascade Material Design</h3>
    </md-card-title>
    <md-card-content>
      <div *ngIf='allStates'>
        <form novalidate [formGroup]="myForm">
          <div class="flex-container" fxLayout="row" fxLayoutAlign="left left">
            <div class="flex-container" fxLayout="row" fxLayoutGap="20px" fxLayoutAlign="space-around space-around" fxFlex="97%">
              <div class="flex-oneStudent" fxFlex="10%">
                <md-select placeholder="State" formControlName="state" required="true" (change)="onSelect($event.target.value)">
                  <md-option *ngFor="let oneState of allStates" [value]="oneState.state">
                    {{ oneState.state }}
                  </md-option>
                </md-select>
              </div>
              <div class="flex-oneStudent" fxFlex="20%">
                <md-select placeholder="City" formControlName="city" required="true">
                  <md-option *ngFor="let oneCity of cityByState" [value]="oneCity.city">
                    {{ oneCity.city }}
                  </md-option>
                </md-select>
              </div>
              <div fxFlex="67%"> </div>
            </div>
          </div>
        </form>
      </div>
    </md-card-content>
  </md-card>

这是主要的组件

import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';

import { StateService } from '../State/state.service';
import { CityService } from '../City/city.service';
import { IState } from '../State/state.interface';
import { ICity } from '../City/city.interface';

import * as _ from 'lodash';

@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.css']
})
export class MainComponent implements OnInit {
  myForm: FormGroup;
  allStates: IState[];
  cityByState: ICity[];

  constructor(public fb: FormBuilder,
    private _StateService: StateService,
    private _CityService: CityService
  ) { }

  ngOnInit() {
    this.myForm = this.fb.group({
      state: '',
      city: ''
    });

    this._StateService.getState()
      .subscribe(
      stateData => this.allStates = _.uniqBy(stateData, 'state')
      );
  }

  onSelect(stateName) {
    console.log ('User selected ' + stateName);
    this._CityService.getCity(stateName)
      .subscribe(
      cityData => this.cityByState = _.filter(cityData, function(o) { return o.state == stateName})
      );

  }

}

这是完整代码的github。 https://github.com/ATXGearHead12/cascade

需要看一下材料源代码https://github.com/angular/material2/blob/master/src/lib/select/select.ts#L247

@Output() change: EventEmitter<MdSelectChange> = new EventEmitter<MdSelectChange>();

如您所见,使用MdSelectChange有效负载发出了事件

export class MdSelectChange {
  constructor(public source: MdSelect, public value: any) { }
}

所以更换

(change)="onSelect($event.target.value)"

(change)="onSelect($event.value)"

* 从 Angular 6. (change) 开始贬值以支持 (selectionChange)
请参阅材料 2 重大更改 > 弃用

(selectionChange)="onSelect($event.value)"

如果您的数据来自数据库,并且您想在角度材料中填充级联下拉列表,这里是完整代码:

html:

<div class="card card-header bg-secondary text-light">Primary address</div>
            <div class="form-row">
                <div class="form-group col-md-6 senecaform-container">
                    <mat-form-field>
                        <mat-label>Country</mat-label>
                        <mat-select formControlName="primaryAddressCountryCtrl" required>
                            <mat-option></mat-option>
                            <mat-option *ngFor="let citem of country" [value]="citem.Id">
                                {{citem.Name}}
                            </mat-option>
                        </mat-select>
                        <mat-error *ngIf="primaryAddressCountryCtrl.hasError('required')">Please choose birth
                            country</mat-error>
                    </mat-form-field>
                </div>
                <div class="form-group col-md-2 senecaform-container ">
                    <mat-form-field>
                        <mat-label>Country</mat-label>
                        <mat-select formControlName="StateProvince" required>
                            <mat-option></mat-option>
                            <mat-option *ngFor="let pitem of provincestatelist" [value]="pitem.Id">
                                {{pitem.Name}}
                            </mat-option>
                        </mat-select>
                        <!-- <mat-error *ngIf="StateProvince.hasError('required')">Please choose birth
                            country</mat-error> -->
                    </mat-form-field>
                </div>

你的组件代码:

 firstFormGroup: FormGroup;
 secondFormGroup: FormGroup;
 thirdFormGroup: FormGroup;
 country;
 provincestatelist;


 constructor(
private staticService: StaticService,
private agentService: AgentService,
private _formBuilder: FormBuilder,
private _activatedRoute: ActivatedRoute,
public formValidationService: FormValidationService
 ) { }


  this.staticService.getCountry().subscribe((country: ICountry) => {
  this.country = country;
});

 this.firstFormGroup = this._formBuilder.group({
  primaryAddressCountryCtrl:['', Validators.required],
  StateProvince: ['',null]
});

//-----this bellow code is used to set your cascade dropdown----//
   this.firstFormGroup.get('primaryAddressCountryCtrl').valueChanges.subscribe(item=> 
  {
  //console.log(item);
   this.staticService.getProvinceState(item).subscribe((province: IProvinceState) => 
  {
    this.provincestatelist = province;
  });
  });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM