Angular4自制一个市县二级联动组件


声明:本文转载自https://my.oschina.net/u/3512877/blog/1576541,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

最近遇到了不少问题,真的是命运多舛。Angular真是让人又爱又恨的框架,恨的是资料太少,遇到问题无从下手。爱的是许多其他框架难以做到的功能,angular却可以轻松做到。

话不多说,最近遇到了一个旧项目改造的问题。拿到前同事做的页面效果:

第一眼就看到了这三个下拉框,按捺不住好奇心的我点了点。原来,第一个下拉框可以选择市属和省属,如果选择市属,那么后面就会出现市、县级两个下拉框,如果是省属,那就隐藏了,这个挺容易的。然后就是要选择市之后,区下拉框要有对应区县选项。emmmm,很典型的二级联动,不过既然分析完了思路,那就开始做吧!首先呢,数据肯定要从后端同事那里拿,调用他的接口把数据填充进去。看看数据是什么样子的:

这里写图片描述

数据略多,就不全部贴出来了。把实体bean创建一下,

Typescript code  // 市级实体类 export class City {      // 市级id     cityId: string;      // 所属类型(0.市属 1.省属)     cityType: number;      // 市级名称(可选属性,若cityType为1时,可不填)     cityName: string;      // 所属区县     counties?: Array<Country>;  }  // 区县级实体类 export class Country {      // 区县id     countryId: string;      // 区县名称     countryName: string;  }  // 填写市县类 export class CityAndCountry {      // 市级id     cityId: string;      // 县级id     countryId: string;      // 市级类型     cityType: number;      // 市县级实体构造器      constructor() {         // 给市级id赋予一个真实城市的id初始值         this.cityId = '***';         // 同上         this.countryId = '***';         // 同上         this.cityType = 0;     } }

实体完成了,开始准备获取数据并填充至实体:

Typescript code  // 二级联动组件 export class CityAreaComponent implements OnInit, OnDestroy {      // 结果码 (用于页面处理显示标识)     result_code: number;      // 市级实体声明     city: City[];      // 县区级实体声明     country: Country[];      // 市县、区级填写实体声明     cac: CityAndCountry;      // 声明订阅对象     subscript: Subscription;      /**     * 构造器     * @param {CityService} service 注入服务     */     constructor (private service: CityService) {         // 结果码 (-1.网络或其他异常 0.无内容 1.请求成功 2.请等待)         this.result_code = 2;         // 初始化填写市区、县级填写实体         cac = new CityAndCountry();         // 初始化数组(这步很重要,有很多人说使用数组相关函数会报未定义异常,是因为没有初始化的原因)         this.city = [];         this.country = [];         // 初始化订阅对象         this.subscript = new Subscription();     }      /**     * 生命周期初始化钩子(生命周期尽量按执行顺序来写,养成好习惯)     */     ngOnInit(): void {         this.getCityArea();     }      /** 获取市县数据 */     getCityArea() {         /** 将请求交付服务处理(service代码比较简单,就不贴了) */         this.subscript = this.service.getCityArea().subscribe(res => {             /** 获取json请求结果 */             const result = res.json();             /** 判断结果返回码 */             switch (result['code']) {                 /** 请求成功,并且有值 */                 case 200:                 /** 改变初始返回码 */                 this.result_code = 1;                 /** 获取并填充数据 */                 this.city = json['city'];                 break;                 /** 其他情况不重复赘述 */             }         }, err => {             /** 显示预设异常信息提示给用户 */             this.result_code = -1;             /** 打印log,尽量使用日志产出 */             console.error(err);         });     }      /** 生命周期销毁钩子 */     ngOnDestroy(): void {         /** 取消订阅 */         this.subscript.unsubscribe();     } }

由于此处是单服务请求,为了让代码比较清晰直观,这里我就不做封装处理了。数据获取了之后就该填充到展示界面了:

Html code  <!-- 所属类型(此处固定,一般为获取后端数据字典数据) --> <select class="city_type" [value]="cac.cityType" [(ngModel)]="cac.cityType">     <!-- 所传内容为整数型 -->     <option value=0>市属</option>     <option value=1>省属</option> </select>  <!-- 市级选择(类型为省属时隐藏) --> <select class="city" [value]="cac.cityId" [(ngModel)]="cac.cityId" *ngIf="city.cityType==0">     <!-- 遍历城市数组 -->     <option *ngFor="let opt of option" [value]="opt.cityId">{{opt.cityName}}</option> </select>

这时候,我们发现县级获取起来好像并不能直接获取,怎么办呢?我突然想到,我在ts里面声明一个变量获取市级选择的id号,然后再拿id去找下属县区,这样就可以轻松拿到了。既然要实时获取变化,那我们就实现检测变化钩子:

Typescript code  // 二级联动组件 export class CityAreaComponent implements OnInit, OnDestroy, DoCheck{     // 声明县区级数组     country: Array<Country>;      constructor() {         /** 重复代码不赘述 */         /** 初始化数组 */         country = [];     }         /** 生命周期检测变化钩子 */     ngDoCheck(): void {         /** 遍历市级数组 */         for (let i = 0; i < this.city.length; i++) {             /** 若选择的市级id和市级数组中的id相吻合 */             if (this.city[i].id == this.cac.countryId) {                 /** 将该索引下的counties数组赋予给区县级数组 */                 this.country = this.city[i].counties;             }             /** 我们无法避免直辖市的情况,所以多一重判断 */             if (this.country.length > 0) {                 /** 为了用户体验,我们要尽量在用户选择市级城市后,默认选择一个区县级城市 */                 this.cac.country.id = this.country[0].id;             }         }     } }

最后再补上区县级下拉框:

Html code  <!-- 区县级下拉框 --> <select [value]="cac.countryId" [(ngModel)]="cac.countryId" *ngIf="cac.cityType==0 && country.length > 0">     <option *ngFor="let count of country" [value]="count.id">{{count.name}}</option> </select>

到此为止,大功告成,再也不用去依赖别人的库了。

由于没有用IDE工具,以上代码可能会有小缺失,若有疑问,请在评论提出。欢迎大神指点改进,谢谢!

本文发表于2017年11月21日 12:33
(c)注:本文转载自https://my.oschina.net/u/3512877/blog/1576541,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1701 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1