当前位置:   article > 正文

如何根据美国的邮编带出对应的州呢_输入邮编对应 州

输入邮编对应 州

项目中没有维护这个对应关系的API,所以我google到了Google map的API,只需要发get请求发送邮编即可。api地址是
http://maps.googleapis.com/maps/api/geocode/json?address=xxx,这里的address就是接受的邮编。
所以现在需求是:用户输入邮政编码后请求该API得到对应的州和city,然后渲染到对应的字段中。
create-client.component.html

  1. <!-- client form -->
  2. <div animated fadeIn>
  3. <form class="client-form" class="form-horizontal" [formGroup]="orgForm">
  4. <div class="row">
  5. <div class="col-md-10">
  6. <div class="card">
  7. <div class="card-header"><strong>Account Information</strong></div>
  8. <div class="card-body">
  9. <div class="row">
  10. <label for="country"
  11. class="col-md-3 form-control-label required-label"><span class="asterisk">*</span>Country:</label>
  12. <div class="col-md-9">
  13. <select style="height: 34px;" class="col-md-5 form-control" id="country" name="country" formControlName="country">
  14. <option *ngFor="let country of countries"
  15. [value]="country">
  16. {{ country }}
  17. </option>
  18. </select>
  19. </div>
  20. </div>
  21. <div class="row">
  22. <label for="postal"
  23. class="col-md-3 form-control-label required-label"><span class="asterisk">*</span>Postal Code:</label>
  24. <div class="col-md-9">
  25. <input id="postal" name="postal"
  26. class="col-md-5 form-control"
  27. formControlName="postal"
  28. placeholder="Enter Client Postal Code" (change)="onPostalChange($event)" >
  29. <span class="col-md-5 login-error-alert" *ngIf="this.isFormInputInvalid('postal') &&
  30. this.orgForm.get('postal').hasError('required')">Postal Code is required</span>
  31. <span class="col-md-5 login-error-alert" *ngIf="this.isFormInputInvalid('postal') &&
  32. !this.orgForm.get('postal').hasError('required') &&
  33. this.orgForm.get('postal').hasError('pattern')">Postal Code must be a 5 digit number</span>
  34. <span class="col-md-5 login-error-alert" *ngIf="this.isPostalCodeInvalid &&
  35. !this.orgForm.get('postal').hasError('pattern') &&
  36. !this.orgForm.get('postal').hasError('required')">Postal Code is not available</span>
  37. </div>
  38. </div>
  39. <div class="row">
  40. <label for="city"
  41. class="col-md-3 form-control-label required-label"><span class="asterisk">*</span>City:</label>
  42. <div class="col-md-9">
  43. <input id="city" name="city" [(ngModel)]="cityName"
  44. class="col-md-5 form-control"
  45. formControlName="city"
  46. placeholder="Enter Client City">
  47. <span class="col-md-5 login-error-alert" *ngIf="this.isFormInputInvalid('city') &&
  48. this.orgForm.get('city').hasError('required')">City is required</span>
  49. <span class="col-md-5 login-error-alert" *ngIf="this.isFormInputInvalid('city') &&
  50. this.orgForm.get('city').hasError('pattern')">City cannot exceed 40 characters</span>
  51. </div>
  52. </div>
  53. <div class="row">
  54. <label for="state"
  55. class="col-md-3 form-control-label required-label"><span class="asterisk">*</span>State:</label>
  56. <div class="col-md-9">
  57. <select style="height: 34px;" class="col-md-5 form-control" id="state" formControlName="state"
  58. [(ngModel)]="stateAbbreviation" (ngModelChange)="onStateChange($event)">
  59. <option *ngFor="let state of stateItems"
  60. [value]="state">
  61. {{ state }}
  62. </option>
  63. </select>
  64. <div *ngIf="orgForm.get('state').touched || orgForm.get('state').dirty">
  65. <span class="col-md-5 login-error-alert" *ngIf="this.isFormInputInvalid('state') &&
  66. this.orgForm.get('state').hasError('required')">State is required</span>
  67. <span class="col-md-5 login-error-alert" *ngIf="this.isStateValueMismatchWithPostalCode"> Postal Code and State Mismatch</span>
  68. </div>
  69. </div>
  70. </div>
  71. </div>
  72. </div>
  73. <div class="modal-footer col-md-10">
  74. <div class="col-md-9">
  75. <div class="col-md-5">
  76. <button type="button" class="btn btn-dark-rs6 col-md-5" id="reset-button-modal"
  77. (click)="orgForm.reset()" style="margin-left: -24px">Reset
  78. </button>
  79. <button type="submit" class="btn btn-green-rs6 col-md-5" id="submit-button-modal"
  80. [disabled]="!orgForm.valid || this.isStateValueMismatchWithPostalCode || isPostalCodeInvalid" (click)="onSubmit()"
  81. style="float: right; margin-right: -15px">Create
  82. </button>
  83. </div>
  84. </div>
  85. </div>
  86. </form>
  87. </div>

子类:create-client.component.ts
 

  1. import { Component } from '@angular/core';
  2. import { FormBuilder, Validators } from '@angular/forms';
  3. import { ActivatedRoute, Params, Router } from '@angular/router';
  4. import { Location } from '@angular/common';
  5. import { Account } from '../../model/account.model';
  6. import { PaymentTermList } from '../../model/payment-term-list.model';
  7. import { PricingPackage } from '../../model/pricing-package.model';
  8. import { Processor } from '../../model/processor.model';
  9. import { RequestBilling } from '../../model/request-billing.model';
  10. import { User } from '../../model/user.model';
  11. import { DialogService } from '../../service/dialog.service';
  12. import { OrganizationService } from '../../service/organization.service';
  13. import { CreateOrganizationComponent } from '../create-organization/create-organization.component';
  14. import {Regex} from '../../model/regex.model';
  15. import { OrganizationType } from '../../model/organization-type.model';
  16. import {UtilService} from '../../service/util.service';
  17. import {Constants} from '../../utility/constants';
  18. import {Utility} from '../../utility/utility';
  19. @Component({
  20. selector: 'app-create-client',
  21. templateUrl: 'create-client.component.html'
  22. })
  23. export class CreateClientComponent extends CreateOrganizationComponent {
  24. account: Account = {
  25. soldBy: '', ownedBy: '', address: {
  26. address1: '', address2: '', city: '', state: '', country: '', postal: ''
  27. }, emailAddress: '', locale: {language: {cultureName: ''}},
  28. processorList: [{name: ''}]
  29. };
  30. countries: string[] = [];
  31. stateItems: string[] = [];
  32. constructor(private fb: FormBuilder, route: ActivatedRoute, dialogService: DialogService,
  33. organizationService: OrganizationService, utilService: UtilService,
  34. router: Router, location: Location, regex: Regex) {
  35. super(route, dialogService, organizationService, router, location, regex, utilService);
  36. this.createForm();
  37. this.title = 'Client Creation';
  38. this.route.queryParams.subscribe((params: Params) => {
  39. this.clientId = params['clientId'];
  40. this.parentOrganizationId = params['parentOrganizationId'];
  41. });
  42. this.initProcessorList();
  43. this.organizationService.getPaymentTerms().subscribe(
  44. (paymentTermList: PaymentTermList) => this.paymentTermList = paymentTermList);
  45. this.utilService.getCountries().subscribe(
  46. (countries: string[] ) => this.countries = countries);
  47. this.utilService.getStates().subscribe(
  48. (states: string[] ) => this.stateItems = states);
  49. }
  50. onSubmit() {
  51. this.updateModel();
  52. super.onSubmit(OrganizationType.Client);
  53. }
  54. updateModel() {
  55. this.model.account.address.city = this.orgForm.get('city').value;
  56. this.model.account.address.state = this.orgForm.get('state').value;
  57. this.model.account.address.postal = this.orgForm.get('postal').value;
  58. this.model.account.address.country = Utility.convertSpecificCountryNameInShort(this.orgForm.get('country').value);
  59. this.model.account.processorList = [];
  60. for (const processor of this.processors) {
  61. if (processor['checked']) {
  62. const p: Processor = {name: processor['name']};
  63. this.model.account.processorList.push(p);
  64. }
  65. }
  66. }
  67. onPostalChange($event) {
  68. this.onPostalChanges(this.orgForm.get('postal').value);
  69. }
  70. private createForm() {
  71. this.orgForm = this.fb.group({
  72. state: ['', [Validators.required, Validators.pattern(this.regex.state)]],
  73. city: ['', [Validators.required, Validators.pattern(this.regex.city)]],
  74. country: ['', [Validators.required]],
  75. postal: ['', [Validators.required, Validators.pattern(this.regex.postalCode)]],
  76. );
  77. }
  78. }

父类:create-organization.component.ts

 

  1. import { HttpErrorResponse, HttpResponse, HttpResponseBase } from '@angular/common/http';
  2. import { Component, ViewChild, ElementRef } from '@angular/core';
  3. import { AbstractControl, FormGroup } from '@angular/forms';
  4. import { ValidationErrors } from '@angular/forms/src/directives/validators';
  5. import { ActivatedRoute, Params, Router} from '@angular/router';
  6. import { Location } from '@angular/common';
  7. import { Observable } from 'rxjs/Observable';
  8. import { Organization } from '../../model/organization.model';
  9. import { Regex } from '../../model/regex.model';
  10. import { DialogService } from '../../service/dialog.service';
  11. import { OrganizationService } from '../../service/organization.service';
  12. import { Utility } from '../../utility/utility';
  13. import { OrganizationType } from '../../model/organization-type.model';
  14. import { UtilService } from '../../service/util.service';
  15. @Component({
  16. selector: 'app-create-organization',
  17. templateUrl: 'create-organization.component.html'
  18. })
  19. export class CreateOrganizationComponent {
  20. parentOrganizationUserName = '';
  21. parentOrganizationId: number;
  22. orgForm: FormGroup;
  23. stateAbbreviationFirstValue = '';
  24. isFirstTimeToChoose = true;
  25. stateAbbreviation = '';
  26. isPostalCodeInvalid = false;
  27. isStateValueMismatchWithPostalCode = false;
  28. cityName = '';
  29. constructor(public route: ActivatedRoute, public dialogService: DialogService, public organizationService: OrganizationService,
  30. private router: Router, public location: Location, public regex: Regex, public utilService: UtilService) {
  31. }
  32. onSubmit(orgType: any) {
  33. let parentOrgId = '';
  34. if (this.parentOrganizationId) {
  35. parentOrgId = this.parentOrganizationId.toString();
  36. }
  37. this.organizationService.createChildOrganization(this.parentOrganizationUserName, parentOrgId, this.model)
  38. .subscribe((response: HttpResponseBase) => {
  39. if (response instanceof HttpResponse) {
  40. this.createdOrgId = response.body['organizationId'];
  41. this.resResult = !response.body['customMessage'];
  42. this.openDialog(this.resResult, orgType, response.body['customMessage']);
  43. } else if (response instanceof HttpErrorResponse) {
  44. this.resErrorResult = response.error['text'];
  45. this.openDialog(false, orgType, this.resErrorResult);
  46. }
  47. }, (error) => {
  48. this.openDialog(false, orgType, '');
  49. });
  50. }
  51. isFormInputInvalid(input: string): boolean {
  52. return Utility.isFormInputInvalid(input, this.orgForm);
  53. }
  54. isUserNameAvailable(control: AbstractControl): Observable<ValidationErrors | null> {
  55. return this.organizationService.getUserNameAvailability(control.value).map((res: any) => res.isUserNameAvailable ? null : res);
  56. }
  57. /**
  58. * Get the state abbreviation with the postal code from google API and judged whether is postal code is valid or not.
  59. * @param postalCode postal code.
  60. */
  61. onPostalChanges(postalCode: string) {
  62. this.isFirstTimeToChoose = true;
  63. if (postalCode) {
  64. this.utilService.getAddressInfoWithPostalCode(postalCode).subscribe(res => {
  65. const address = Utility.filterStateWithPostalCodeFromGoogleApi(res);
  66. if (address && address.state) {
  67. this.isPostalCodeInvalid = false;
  68. this.stateAbbreviation = address.state;
  69. this.cityName = address.city;
  70. this.isStateValueMismatchWithPostalCode = false;
  71. } else {
  72. this.isPostalCodeInvalid = true;
  73. }
  74. });
  75. }
  76. }
  77. /**
  78. * When changed the state select value then will call this method,it used to confirm whether
  79. * the state value is match with the postal code or not.
  80. * @param stateAbbreviationFirstValue the abbreviation of the firstly selected state value.
  81. * @param stateAbbreviationNewValue the abbreviation of the now selected state value.
  82. */
  83. isStateAndPostalCodeValid(stateAbbreviationNewValue: string, stateAbbreviationFirstValue: string) {
  84. if (stateAbbreviationNewValue !== undefined && stateAbbreviationFirstValue !== undefined) {
  85. if (stateAbbreviationFirstValue.match(stateAbbreviationNewValue)) {
  86. this.isStateValueMismatchWithPostalCode = false;
  87. } else {
  88. this.isStateValueMismatchWithPostalCode = true;
  89. }
  90. }
  91. }
  92. /**
  93. * change event on state field
  94. * save the first value of state field,and judge whether the postal code and state is match or not.
  95. */
  96. onStateChange($event) {
  97. if (this.isFirstTimeToChoose === true) {
  98. this.stateAbbreviationFirstValue = this.stateAbbreviation;
  99. this.isFirstTimeToChoose = false;
  100. }
  101. this.isStateAndPostalCodeValid(this.stateAbbreviation, this.stateAbbreviationFirstValue);
  102. }
  103. }

Utility.ts,解析谷歌api返回的json
 

  1. /**
  2. * Filter the results of requesting google api, retain the state's abbreviation and the city name.
  3. * @param res the results from calling the google API.
  4. * @returns Address including the abbreviation of State and the city name.
  5. */
  6. static filterStateWithPostalCodeFromGoogleApi(res: any): Address {
  7. const address: Address = {};
  8. if (res['results'].length === 0) {
  9. return res[0];
  10. } else {
  11. const stateNames = res['results'][0]['address_components'].filter(resp => resp['types'][0] === 'administrative_area_level_1')
  12. .map(re => re['short_name']);
  13. const cityNames = res['results'][0]['address_components'].filter(resp => resp['types'][0] === 'locality')
  14. .map(re => re['long_name']);
  15. address.state = stateNames[0];
  16. address.city = cityNames[0];
  17. return address;
  18. }
  19. }

 

测试点击事件ngModelChange

  1. it('should go from model to change event', async(() => {
  2. const fixture = TestBed.createComponent(CreateMerchantComponent);
  3. const comp = fixture.componentInstance;
  4. spyOn(comp, 'onStateChange');
  5. comp.stateItems = states;
  6. comp.stateAbbreviation = states[1];
  7. fixture.detectChanges();
  8. const select = fixture.debugElement.query(By.css('#state'));
  9. fixture.whenStable().then(() => {
  10. select.nativeElement.dispatchEvent(new Event('change'));
  11. fixture.detectChanges();
  12. expect(comp.onStateChange).toHaveBeenCalledWith('AK');
  13. });
  14. }));

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号