HarmonyOS实现表单页面的输入,必填校验和提交
一. 样例介绍
本篇Codelab基于input组件、label组件和dialog组件,实现表单页面的输入、必填校验和提交:
1. 为input组件设置不同类型(如:text,email,date等),完成表单页面。
2. 对表单页面中的用户名、电子邮件、爱好输入框进行必填校验。
3. 使用弹框选择性别、爱好。
相关概念
● input组件:交互式组件,包括单选框,多选框,按钮和单行文本输入框。
● label组件:为input、button、textarea组件定义相应的标注,点击该标注时会触发绑定组件的点击效果。
● dialog组件:自定义弹窗容器。
完整示例
二. 环境搭建
我们首先需要完成HarmonyOS开发环境搭建,可参照如下步骤进行。
软件要求
● DevEco Studio版本:DevEco Studio 3.1 Release及以上版本。
● HarmonyOS SDK版本:API version 9及以上版本。
硬件要求
● 设备类型:华为手机或运行在DevEco Studio上的华为手机设备模拟器。
● HarmonyOS系统:3.1.0 Developer Release及以上版本。
环境搭建
1. 安装DevEco Studio,详情请参考下载和安装软件。
2. 设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:
● 如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。
● 如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。
1. 开发者可以参考以下链接,完成设备调试的相关配置:
● 使用真机进行调试
三.代码结构解读
本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在源码下载或gitee中提供。
├──entry/src/main/js // 代码区 │ └──MainAbility │ ├──common │ │ ├──constant │ │ │ └──commonConstants.js // 公共常量 │ │ └──images // 图片资源目录 │ ├──i18n │ │ ├──en-US.json // 英文国际化 │ │ └──zh-CN.json // 中文国际化 │ ├──pages │ │ └──index │ │ ├──index.css // 表单页面样式 │ │ ├──index.hml // 表单页面 │ │ └──index.js // 表单页面逻辑 │ └──app.js // 程序入口 └──entry/src/main/resource // 应用静态资源目录
四. 页面设计
页面包括用户名、电子邮箱、出生日期、身高、性别、爱好输入框和提交按钮,点击提交按钮进行必填校验。
<!-- index.hml --> <div class="container"> ... <div class="user-area"> <image class="image" src="{{ urls.user }}"></image> <div class="input-label"> <image src="{{ urls.required }}"></image> <label class="label" target="user">{{ $t('strings.user') }}</label> </div> <div class="input-div"> <input class="input" id="user" type="text" placeholder="{{ $t('strings.user') }}" onchange="inputChange" ontranslate="translate"></input> </div> </div> <div class="input-area"> <image src="{{ urls.email }}"></image> <div class="input-label"> <image src="{{ urls.required }}"></image> <label class="label" target="email">{{ $t('strings.email') }}</label> </div> <div class="input-div"> <input class="input" id="email" type="email" placeholder="{{ $t('strings.email') }}" onchange="inputChange"> </input> </div> </div> <div class="input-area"> <image src="{{ urls.date }}"></image> <div class="input-label"> <label class="label" target="date">{{ $t('strings.birthday') }}</label> </div> <div class="input-div"> <input class="input" id="date" type="date" placeholder="{{ $t('strings.date') }}" onchange="inputChange"> </input> </div> </div> <div class="input-area"> <image src="{{ urls.height }}"></image> <div class="input-label"> <label class="label" target="height">{{ $t('strings.height_holder') }}</label> </div> <div class="input-div"> <input class="input" id="height" type="number" placeholder="{{ $t('strings.height') }}" onchange="inputChange"></input> </div> </div> <div class="input-area"> <image src="{{ urls.gender }}"></image> <div class="input-label"> <label class="label" target="gender">{{ $t('strings.gender') }}</label> </div> <div class="input-div" onclick="openGender"> <input class="input select" id="gender" type="text" placeholder="{{ $t('strings.gender') }}" softkeyboardenabled="false" value="{{ genderObj[gender] }}"></input> <image src="{{ urls.spinner }}"></image> </div> </div> <divclass="input-area"> <image src="{{ urls.hobby }}"></image> <divclass="input-label"> <image src="{{ urls.required }}"></image> <labelclass="label" target="hobbies">{{ $t('strings.hobbies') }}</label> </div> <divclass="input-div" onclick="openHobby"> <input class="input select" id="hobbies" type="text" placeholder="{{ $t('strings.hobby') }}" softkeyboardenabled="false" value="{{ hobbies.join(',') }}"></input> <image src="{{ urls.spinner }}"></image> </div> </div> <button type="capsule" onclick="buttonClick">{{ $t('strings.submit') }}</button> ... </div>
效果如图所示:
点击性别输入框弹出性别单选框,点击爱好输入框弹出爱好多选框。
<!-- index.hml --> <div class="container"> ... <dialog id="genderDialog"> <div class="gender-dialog"> <text>{{ $t('strings.gender_select') }}</text> <div> <text>{{ $t('strings.gender_male') }}</text> <input if="{{ gender === 0 }}" class="radio" type="radio" checked="true" name="radio" value="{{ $t('strings.gender_male') }}" onchange="onRadioChange"></input> <input if="{{ gender === 1 }}" class="radio" type="radio" checked="false" name="radio" value="{{ $t('strings.gender_male') }}" onchange="onRadioChange"></input> </div> <divider vertical="false"></divider> <div> <text>{{ $t('strings.gender_female') }}</text> <input if="{{ gender === 0 }}" class="radio" type="radio" checked="false" name="radio" value="{{ $t('strings.gender_female') }}"></input> <input if="{{ gender === 1 }}" class="radio" type="radio" checked="true" name="radio" value="{{ $t('strings.gender_female') }}"></input> </div> <div class="button"> <text onclick="closeGender">{{ $t('strings.cancel') }}</text> <divider vertical="true"></divider> <text onclick="confirmGender">{{ $t('strings.determined') }}</text> </div> </div> </dialog> <dialog id="hobbyDialog"> <div class="hobby-dialog"> <text>{{ $t('strings.hobby') }}</text> <div> <text>{{ $t('strings.hobby_swim') }}</text> <input class="checkbox" type="checkbox" checked="{{ hobbies.indexOf(hobbiesOjb[0]) !== -1 }}" value="{{ hobbiesOjb[0] }}" onchange="checkboxOnChange"></input> </div> <div> <text>{{ $t('strings.hobby_fitness') }}</text> <input class="checkbox" type="checkbox" checked="{{ hobbies.indexOf(hobbiesOjb[1]) !== -1 }}" value="{{ hobbiesOjb[1] }}" onchange="checkboxOnChange"></input> </div> <div> <text>{{ $t('strings.hobby_soccer') }}</text> <input class="checkbox" type="checkbox" checked="{{ hobbies.indexOf(hobbiesOjb[2]) !== -1 }}" value="{{ hobbiesOjb[2] }}" onchange="checkboxOnChange"></input> </div> <div> <text>{{ $t('strings.hobby_basketball') }}</text> <input class="checkbox" type="checkbox" checked="{{ hobbies.indexOf(hobbiesOjb[3]) !== -1 }}" value="{{ hobbiesOjb[3] }}" onchange="checkboxOnChange"></input> </div> <div> <text>{{ $t('strings.hobby_reading_book') }}</text> <input class="checkbox" type="checkbox" checked="{{ hobbies.indexOf(hobbiesOjb[4]) !== -1 }}" value="{{ hobbiesOjb[4] }}" onchange="checkboxOnChange"></input> </div> <divclass="button"> <text onclick="closeHobby">{{ $t('strings.cancel') }}</text> <divider vertical="true"></divider> <text onclick="confirmHobby">{{ $t('strings.determined') }}</text> </div> </div> </dialog> </div>
效果如图所示:
五. 后台逻辑处理
用户名、电子邮箱、出生日期、身高输入框中值发生变化时,会在data对象中实时更新。
// index.js export default { data: { ... user: '', email: '', date: '', height: '', ... }, ... // 实时保存输入框内容 inputChange(event) { let idName = event.target.id; if (idName === CommonConstants.USER) { this.user = event.value; } else if (idName === CommonConstants.EMAIL) { this.email = event.value; } else if (idName === CommonConstants.DATE) { this.date = event.value; } else if (idName === CommonConstants.HEIGHT) { this.height = event.value; } }, ... }
通过自定义弹框选择性别、爱好。在弹框中点击取消按钮关闭当前弹框,点击确定按钮先设置所选值再关闭弹框。
// index.js export default { data: { ... genderObj: [], genderTemp: 0, gender: 0, hobbiesOjb: [], hobbiesTemp: [], hobbies: [] }, ... // 打开性别弹框 openGender() { this.$element('genderDialog').show(); }, // 重新选择性别 onRadioChange(event) { if (event.checked) { this.genderTemp = 0; } else { this.genderTemp = 1; } }, // 关闭性别弹框 closeGender() { this.$element('genderDialog').close(); }, // 性别弹框中点击“确定” confirmGender() { this.gender = this.genderTemp; this.closeGender(); }, // 打开爱好弹框 openHobby() { this.$element('hobbyDialog').show(); }, // 关闭爱好弹框 closeHobby() { this.$element('hobbyDialog').close(); }, // 在爱好弹开中点击“确定” confirmHobby() { let that = this; let copyHobbies = Object.create(Object.getPrototypeOf(this.hobbiesTemp)); Object.getOwnPropertyNames(this.hobbiesTemp).forEach((items) => { let item = Object.getOwnPropertyDescriptor(that.hobbiesTemp, items); Object.defineProperty(copyHobbies, items, item); }) this.hobbies = copyHobbies; this.closeHobby(); }, ... // 选择爱好 checkboxOnChange(event) { let currentVal = event.currentTarget.attr.value; if (event.checked) { this.hobbiesTemp.push(currentVal); } else { this.hobbiesTemp = this.hobbiesTemp.filter(item => { return item !== currentVal; }); } }, ... }
点击提交按钮对表单进行提交前,先对用户名、密码、电子邮件、爱好进行必填校验,再通过正则表达式对出生日期进行“yyyy-mm-dd”格式校验、对身高进行整数或浮点数校验。
// index.js export default { ... // 表单提交验证 buttonClick() { if (this.user === '') { this.showPrompt(this.$t('strings.user_check_null')); return; } if (this.email === '') { this.showPrompt(this.$t('strings.email_check_null')); return; } if (this.hobbies.length === 0) { this.showPrompt(this.$t('strings.hobby_check_null')); return; } if ((this.date !== '') && (!this.checkDateInput(this.date))) { this.showPrompt(this.$t('strings.date_not_format')); return; } if ((this.height !== '') && (!this.checkHeight(this.height))) { this.showPrompt(this.$t('strings.height_not_format')); return; } this.showPrompt(this.$t('strings.success')); }, ... // 表单验证结果 showPrompt(msg) { prompt.showToast({ message: msg, duration: CommonConstants.DURATION }); }, ... }
总结
您已经完成了本次Codelab的学习,并了解到以下知识点:
1. input组件的使用。
2. label组件的使用。
3. dialog组件的使用。