利用Ionic2 + angular4实现一个地区选择组件


Posted in Javascript onJuly 27, 2017

前言

本文主要给大家介绍的是关于利用Ionic2 + angular4实现一个地区选择组件的相关内容,为什么会有这篇文章?主要是因为最近在项目重构的过程中,发现之前用mobiscroll写的地区选择指令在angular2中很难重用(毕竟是用typeScript)。于是就萌生了自己写一个组件的想法。

想和之前一样基于mobiscroll去写,但是发现非常耗费精力,于是某日万般无奈这下搜了一下相关的组件,不出所料已经有人写了。https://www.npmjs.com/package...但是此组件并不符合我的要求。我不是单纯的选择省市区,还可能是选择省市或者省。于是参照此项目基于ionic2的picker写了一个公用组件。下面话不多说了,感兴趣的朋友们下面来一起看看详细的介绍:

具体代码如下:

AreasSelect.ts

import {PickerController} from "ionic-angular";
import {Component, EventEmitter, Output, Input} from "@angular/core";
import {areasList} from "../../datasource/areas";

@Component({
 selector: 'areas-select',
 templateUrl: 'areasSelect.com.html',
})
export class AreasSelect {
 constructor(protected Picker: PickerController) {
 }
 private picker;
 private provinceCol = 0; // 省列
 private cityCol = 0; // 市列
 private regionCol = 0; // 区列
 private pickerColumnCmps; // picker纵列数据实例
 private isOpen = false; // 是否被创建
 private pickerCmp; // picker 实例
 private value = ''; // 选中后的数据
 @Input() citiesData = areasList; // 地区数据(默认为areas.ts的数据)
 @Input() cancelText = '关闭'; // 关闭按钮文本
 @Input() doneText = '完成'; // 完成按钮文本
 @Input() separator = ''; // 数据衔接模式
 @Input() level = 3; // 等级设置 最高为三级
 /**
 * 关闭时触发的事件
 * 没有值返回
 * @type {EventEmitter}
 */
 @Output() cancel: EventEmitter<any> = new EventEmitter(); // 关闭事件
 /**
 * 完成时触发的事件
 * 返回值为obj
 * obj = {data: object,value: string} data为对应的省市区和编码
 * @type {EventEmitter}
 */
 @Output() done: EventEmitter<any> = new EventEmitter(); // 完成事件
 /**
 * 打开地区选择器
 * 基本思路
 * 1.创建picker
 * 2. 先把数据处理成省市区分开的数组
 * 3. 将数据以列的形式给到picker
 * 4. 设置数据显示样式(picker)
 * 5. 生成picker
 */
 private open() {
 let pickerOptions = {
 buttons: [
 {
 text: this.cancelText,
 role: 'cancel',
 handler:() => {
 this.cancel.emit(null);
 }
 },
 {
 text: this.doneText,
 handler: (data) =>{
 this.onChange(data);
 this.done.emit({
 data: data,
 value: this.value
 });
 }
 }
 ]
 };
 this.picker = this.Picker.create(pickerOptions);
 this.generate();// 加载
 this.validate(this.picker); // 渲染
 this.picker.ionChange.subscribe(() => {
 this.validate(this.picker);
 });
 // 生成
 this.picker.present(pickerOptions).then(() => {
 this.pickerCmp = this.picker.instance;
 this.pickerColumnCmps = this.pickerCmp._cols.toArray();
 this.pickerColumnCmps.forEach(function (col) {
 return col.lastIndex = -1;
 });
 });
 this.isOpen = true;
 this.picker.onDidDismiss(function () {
 this.isOpen = false;
 });
 }

 /** 对数据进行处理,并移交给picker
 *
 */
 private generate() {
 let values = this.value.toString().split(this.separator);
 // Add province data to picker
 let provinceCol = {
 name: 'province',
 options: this.citiesData.map(function (province) {
 return {text: province.name, value: province.code, disabled: false};
 }),
 selectedIndex: 0
 };
 let provinceIndex = this.citiesData.findIndex(function (option) {
 return option.name == values[0];
 });
 provinceIndex = provinceIndex === -1 ? 0 : provinceIndex;
 provinceCol.selectedIndex = provinceIndex;
 this.picker.addColumn(provinceCol);
 // Add city data to picker
 let cityColData = this.citiesData[provinceCol.selectedIndex].children;
 let cityCol;

 if (this.level >= 2) {
 cityCol = {
 name: 'city',
 options: cityColData.map(function (city) {
 return {text: city.name, value: city.code, disabled: false};
 }),
 selectedIndex: 0
 };
 let cityIndex = cityColData.findIndex(function (option) {
 return option.name == values[1];
 });
 cityIndex = cityIndex === -1 ? 0 : cityIndex;
 cityCol.selectedIndex = cityIndex;
 this.picker.addColumn(cityCol);
 }
 // Add region data to picker
 let regionData, regionCol;

 if (this.level === 3) {
 regionData = this.citiesData[provinceCol.selectedIndex].children[cityCol.selectedIndex].children;
 regionCol = {
 name: 'region',
 options: regionData.map(function (city) {
 return {text: city.name, value: city.code, disabled: false};
 }),
 selectedIndex: 0
 };
 let regionIndex = regionData.findIndex(function (option) {
 return option.name == values[2];
 });
 regionIndex = regionIndex === -1 ? 0 : regionIndex;
 regionCol.selectedIndex = regionIndex;
 this.picker.addColumn(regionCol);
 }
 this.divyColumns(this.picker);
 }

 /**设置数据显示样式
 * @param picker
 */
 private divyColumns(picker) {
 let pickerColumns = this.picker.getColumns(); // 获取列数据
 let columns = [];
 pickerColumns.forEach(function (col, i) {
 columns.push(0);
 col.options.forEach(function (opt) {
 if (opt && opt.text && opt.text.length > columns[i]) {
 columns[i] = opt.text.length;
 }
 });
 });
 if (columns.length === 2) {
 let width = Math.max(columns[0], columns[1]);
 pickerColumns[0].align = 'right';
 pickerColumns[1].align = 'left';
 pickerColumns[0].optionsWidth = pickerColumns[1].optionsWidth = width * 17 + "px";
 }
 else if (columns.length === 3) {
 let width = Math.max(columns[0], columns[2]);
 pickerColumns[0].align = 'right';
 pickerColumns[1].columnWidth = columns[1] * 33 + "px";
 pickerColumns[0].optionsWidth = pickerColumns[2].optionsWidth = width * 17 + "px";
 pickerColumns[2].align = 'left';
 }
 }

 /**
 * 验证数据
 * @param picker
 */
 private validate(picker) {
 let _this = this;
 let columns = picker.getColumns();
 let provinceCol = columns[0];
 let cityCol = columns[1];
 let regionCol = columns[2];
 if (cityCol && this.provinceCol != provinceCol.selectedIndex) {
 cityCol.selectedIndex = 0;
 let cityColData = this.citiesData[provinceCol.selectedIndex].children;
 cityCol.options = cityColData.map(function (city) {
 return {text: city.name, value: city.code, disabled: false};
 });
 if (this.pickerColumnCmps && cityCol.options.length > 0) {
 setTimeout(function () {
 return _this.pickerColumnCmps[1].setSelected(0, 100);
 }, 0);
 }
 }
 if (regionCol && (this.cityCol != cityCol.selectedIndex || this.provinceCol != provinceCol.selectedIndex)) {
 let regionData = this.citiesData[provinceCol.selectedIndex].children[cityCol.selectedIndex].children;
 regionCol.selectedIndex = 0;
 regionCol.options = regionData.map(function (city) {
 return {text: city.name, value: city.code, disabled: false};
 });
 if (this.pickerColumnCmps && regionCol.options.length > 0) {
 setTimeout(function () {
 return _this.pickerColumnCmps[2].setSelected(0, 100);
 }, 0);
 }
 }
 this.provinceCol = provinceCol.selectedIndex;
 this.cityCol = cityCol ? cityCol.selectedIndex : 0;
 this.regionCol = regionCol ? regionCol.selectedIndex : 0;
 }

 /**
 * 设置value
 * @param newData
 */
 private setValue(newData) {
 if (newData === null || newData === undefined) {
 this.value = '';
 }
 else {
 this.value = newData;
 }
 }

 /**
 * 获取value值
 * @returns {string}
 */
 private getValue() {
 return this.value;
 }

 /**
 * 改变value值的显示
 * @param val
 */
 private onChange(val) {
 this.setValue(this.getString(val));
 }

 /**
 * 获取当前选择的地区数据
 * @param newData
 * @returns {string}
 */
 private getString(newData) {
 if (newData['city']) {
 if (newData['region']) {
 return "" + newData['province'].text + this.separator + (newData['city'].text || '') + this.separator + (newData['region'].text || '');
 }
 return "" + newData['province'].text + this.separator + (newData['city'].text || '');
 }
 return "" + newData['province'].text;
 }
}

areasSelect.com.html

其实是不需要对应的template的,但是为了能和父级传参,这里创建了一个空的template

<div></div>

具体用法:

在需要用到的页面调用

test.page.html

<ion-content>
 <button ion-button block icon-left color="light" (tap)="showAreasSelect()">地区选择</button>
</ion-content>
<areas-select #areasSelect [level]="3" (cancel)="closeSelect()" (done)="done($event)"></areas-select>

test.page.ts

import {Component, ElementRef, Injector, ViewChild} from "@angular/core";
import {BasePage} from "../base.page";

@Component({
 templateUrl: 'test.page.html',
 styles: []
})
export class TestPage extends BasePage {
 constructor(protected rt: ElementRef, protected ij: Injector) {
 super(rt, ij);
 }
 @ViewChild('areasSelect') areasSelect;
 showAreasSelect() {
 this.areasSelect.open();
 }
 done(data) {
 this.showAlert(JSON.stringify(data));
 }
 closeSelect() {
 this.showAlert('you click close');
 } 
}

没有地区数据json或ts的文件可以去这里获取:http://xiazai.3water.com/201707/yuanma/regional_data(3water.com).rar

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
翻译整理的jQuery使用查询手册
Mar 07 Javascript
jQuery toggle()设置CSS样式
Nov 05 Javascript
JavaScript 直接操作本地文件的实现代码
Dec 01 Javascript
js 走马灯简单实例
Nov 21 Javascript
JS实现侧悬浮浮动实例代码
Nov 29 Javascript
jquery图形密码实现方法
Mar 11 Javascript
jQuery oLoader实现的加载图片和页面效果
Mar 14 Javascript
jQuery解析XML文件同时动态增加js文件的方法
Jun 01 Javascript
详解vue-router和vue-cli以及组件之间的传值
Jul 04 Javascript
angular实现input输入监听的示例
Aug 31 Javascript
jQuery实现条件搜索查询、实时取值及升降序排序的方法分析
May 04 jQuery
jquery 验证用户名是否重复代码实例
May 14 jQuery
vue单页应用中如何使用jquery的方法示例
Jul 27 #jQuery
详解win7 cmd执行vue不是内部命令的解决方法
Jul 27 #Javascript
Vue2.0如何发布项目实战
Jul 27 #Javascript
在Vue中如何使用Cookie操作实例
Jul 27 #Javascript
vue 怎么创建组件及组件使用方法
Jul 27 #Javascript
详解Angular-cli生成组件修改css成less或sass的实例
Jul 27 #Javascript
Vue中如何实现轮播图的示例代码
Jul 27 #Javascript
You might like
ajax+php打造进度条 readyState各状态
2010/03/20 PHP
Save a File Using a File Save Dialog Box
2007/06/18 Javascript
javascript 客户端验证上传图片的大小(兼容IE和火狐)
2009/08/15 Javascript
用jQuery打造TabPanel效果代码
2010/05/22 Javascript
jquery 单击li防止重复加载的实现代码
2010/12/24 Javascript
myFocus slide3D v1.1.0 使用方法与下载
2011/01/12 Javascript
Javascript页面添加到收藏夹的简单方法
2013/08/07 Javascript
使用Nodejs开发微信公众号后台服务实例
2014/09/03 NodeJs
node.js中的fs.closeSync方法使用说明
2014/12/17 Javascript
jQuery+AJAX实现无刷新下拉加载更多
2015/07/03 Javascript
JS实现的仿淘宝交易倒计时效果
2015/11/27 Javascript
关于Vue.js一些问题和思考学习笔记(1)
2016/12/02 Javascript
angularJS+requireJS实现controller及directive的按需加载示例
2017/02/20 Javascript
javascript+html5+css3自定义弹出窗口效果
2017/10/26 Javascript
NW.js 简介与使用方法
2018/02/01 Javascript
vue 组件高级用法实例详解
2018/04/11 Javascript
angular2 组件之间通过service互相传递的实例
2018/09/30 Javascript
vue实现记事本功能
2019/06/26 Javascript
no-vnc和node.js实现web远程桌面的完整步骤
2019/08/11 Javascript
vue项目接口域名动态获取操作
2020/08/13 Javascript
JavaScript事件委托实现原理及优点进行
2020/08/29 Javascript
整理Python最基本的操作字典的方法
2015/04/24 Python
Python基于pygame实现图片代替鼠标移动效果
2015/11/11 Python
python字符串的方法与操作大全
2018/01/30 Python
Python 网络爬虫--关于简单的模拟登录实例讲解
2018/06/01 Python
win10从零安装配置pytorch全过程图文详解
2020/05/08 Python
用python进行视频剪辑
2020/11/02 Python
销售辞职报告范文
2014/01/12 职场文书
社团招新策划书
2014/02/04 职场文书
中学教师教育感言
2014/02/21 职场文书
2014年公务员思想汇报范文:全心全意为人民服务
2014/03/06 职场文书
广播节目策划方案
2014/05/23 职场文书
少年派的奇幻漂流观后感
2015/06/08 职场文书
欠条样本
2015/07/03 职场文书
如何利用STAR法则制作留学文书?
2019/08/26 职场文书
Nginx已编译的nginx-添加新模块
2021/04/01 Servers