• HarmonyOS 实现表单页面的输入,必填校验和提交


    一. 样例介绍

    本篇 Codelab 基于 input 组件、label 组件和 dialog 组件,实现表单页面的输入、必填校验和提交:

    1.  为 input 组件设置不同类型(如:text,email,date 等),完成表单页面。

    2.  对表单页面中的用户名、电子邮件、爱好输入框进行必填校验。

    3.  使用弹框选择性别、爱好。

    相关概念

    ● input组件:交互式组件,包括单选框,多选框,按钮和单行文本输入框。

    ● label组件:为 input、button、textarea 组件定义相应的标注,点击该标注时会触发绑定组件的点击效果。

    ● dialog组件:自定义弹窗容器。

    完整示例

    gitee源码地址

    二. 环境搭建

    我们首先需要完成 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                    // 应用静态资源目录
    

    四. 页面设计

    页面包括用户名、电子邮箱、出生日期、身高、性别、爱好输入框和提交按钮,点击提交按钮进行必填校验。

    <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>    <div class="input-area">        <image src="{{ urls.hobby }}"></image>        <div class="input-label">            <image src="{{ urls.required }}"></image>            <label class="label" target="hobbies">{{ $t('strings.hobbies') }}</label>        </div>        <div class="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>
    
    

    效果如图所示:

    点击性别输入框弹出性别单选框,点击爱好输入框弹出爱好多选框。

    <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>            <div class="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.jsexport 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.jsexport 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.jsexport 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 组件的使用。

  • 相关阅读:
    文件、异常、模块
    element-plus el-cascader 级联组件清空所选数据方法
    以矩阵的形式,对点或线段或多边形绕固定点旋转方法
    Python函数和代码复用
    Mysql词法分析实验(一)
    python在centos下安装以及配置
    【Java 数据结构】栈与OJ题
    了解世界杯赔率,让您运气更‘好‘(个人分享)
    合宙Air724UG LuatOS-Air LVGL API控件-表格(Table)
    Hadoop系列——大数据概念day1-1
  • 原文地址:https://blog.csdn.net/HarmonyOSDev/article/details/132688894