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

news2024/10/6 14:29:42

一. 样例介绍

本篇 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                    // 应用静态资源目录

四. 页面设计

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

<!-- 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>    <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>

效果如图所示:

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

<!-- 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>            <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 组件的使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/974215.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Burp插件HaE与Authz用法

HaE与Authz均为BurpSuite插件生态的一员&#xff0c;两者搭配可以避免“越权”、“未授权”两类漏洞的重复测试行为。&#xff08;适用于业务繁杂&#xff0c;系统模块功能多的场景&#xff09; 两个插件都可以在store里安装 安装完后&#xff0c;点击Filter Settings勾选Sho…

DSP_TMS320F28377D_算法加速方法4_C语言编程优化

前面3篇的优化思路是从硬件本身和函数库这些方向去加速&#xff0c; 本文则仅从代码本身的效率去考虑加速的方法。 1、用全局变量比用局部变量快 void testfunction1(){ // 局部变量int i;double s,a,b;a 1.023;b 12.23;for(i 0; i < 1000; i){s __divf32(a,b);} }int …

这3个教学难题,你中招了吗?

在当今教育领域&#xff0c;提高教育质量和学生学习成果是学校和教育机构的首要任务之一。教育管理者、教师和政策制定者都在寻求创新的方法来监督和改进教育过程。 在线巡课系统应运而生&#xff0c;成为教育界的一项重要工具&#xff0c;旨在帮助学校管理者更好地理解教育实践…

无涯教程-JavaScript - ISOWEEKNUM函数

描述 ISOWEEKNUM函数返回给定日期的年份的ISO周编号。 语法 ISOWEEKNUM (date)争论 Argument描述Required/OptionalDateDate is the date-time code used by Excel for date and time calculation.Required Notes Microsoft Excel将日期存储为连续数字,因此可以在计算中使…

【网络教程】记一次使用Docker手动搭建BT宝塔面板的全过程(包含问题解决如:宝塔面板无法开启防火墙,ssh,nginx等)

文章目录 准备安装安装宝塔面板开启ssh和修改ssh的密码导出镜像问题解决宝塔面板无法开启防火墙无法启动ssh设置密码nginx安装失败设置开机启动相关服务准备 演示的系统环境:Ubuntu 22.04.3 LTS更新安装/升级docker到最新版本升级docker相关命令如下# 更新软件包列表并自动升级…

期权交易策略及案例的基本策略有哪些?

目前我国上市交易的期权品种日益丰富&#xff0c;期权的基础的交易方法是建立相应头寸再反向平仓&#xff0c;赚取权利金差价&#xff0c;也可以持有期权到期行权。除了基础的交易方法之外&#xff0c;期权还有一些组合策略&#xff0c;下文介绍期权交易策略及案例的基本策略有…

K210-AI视觉

1、颜色识别 image.find_blobs( thresholds, invertFalse, roi, x_stride2, y_stride1, area_threshold10, pixels_threshold10, mergeFalse, margin0, threshold_cbNone, merge_cbNone)thresholds : 必须是元组列表。 [(lo, hi), (lo, hi), …, (lo, hi)] 定义你想追踪…

Python数据分析实战-Series转DataFrame并将index设为新的一列(附源码和实现效果)

实现功能 Series转DataFrame并将index设为新的一列 实现代码 import pandas as pd# 创创建series series pd.Series([1, 2, 3, 4, 5])# 创建一个DataFrame对象 data {column_name: series} df pd.DataFrame(data)# 重新设置索引&#xff0c;将原有的索引作为新的一列 df.r…

计算机的 bit(比特)和Byte(字节)

我们来说说和数据有关的单位 bit 和 Byte。 在说这这个数据当我之前&#xff0c;大家应该都知道计算机实际上只能处理0和1。 计算机能够把0和1转换为电路中的信号来进行计算&#xff0c;这个其实就是计算机的本质。 单位定义 我们先对需要使用的单位进行一些定义。 bit&…

Swift 周报 第三十六期

文章目录 前言新闻和社区消息称苹果公司和印度财政部官员磋商&#xff0c;扩大在印度的制造产能iPhone 15 Pro 机型新增泰坦灰iPhone 15 全系配 USB-C 苹果拒绝接口和安卓互通 提案正在审查的提案 Swift论坛推荐博文话题讨论关于我们 前言 本期是 Swift 编辑组整理周报的第三十…

AcWing 787:归并排序

【题目来源】https://www.acwing.com/problem/content/789/【题目描述】 给定你一个长度为 n 的整数数列。 请你使用归并排序对这个数列按照从小到大进行排序。 并将排好序的数列按顺序输出。【输入格式】 输入共两行&#xff0c;第一行包含整数 n。 第二行包含 n 个整数&#…

鼠标知识系列之星闪鼠标

随着 2023.8.4 华为 HDC 大会的落幕&#xff0c;一个新的名词开始进入了人们的视线&#xff1a;星闪 NaerLink&#xff0c;随着星闪技术引入键鼠圈子的还有一个名词&#xff1a;星闪鼠标。 正如我们之前鼠标知识分享系列提到过的&#xff0c;目前市面上的鼠标主要是有线鼠标和…

数据库原理及应用(MySQL)

建议大屏观看&#xff0c;避免格式错误&#xff0c;影响观感 目录 第一章 数据库系统概述 1.数据库系统概述 1.1.信息 1.2.数据 1.3.信息和数据之间的联系 1.4.数据库&#xff08;DB&#xff09; 1.5.数据库管理系统&#xff08;DBMS&#xff09; 1.6.数据库管理系统的…

简单了解ARP协议

目录 一、什么是ARP协议&#xff1f; 二、为什么需要ARP协议&#xff1f; 三、ARP报文格式 四、广播域是什么&#xff1f; 五、ARP缓存表是什么&#xff1f; 六、ARP的类型 6.1 ARP代理 6.2 免费ARP 七、不同网络设备收到ARP广播报文的处理规则 八、ARP工作机制原理 …

楠姐技术漫话:接着唠唠社区发现 | 京东云技术团队

★ halo&#xff0c;大家好很开心又和大家见面了 ★ 在第一篇 楠姐技术漫画&#xff1a;图计算的那些事 发布之后&#xff0c;楠姐收到了很多建议、鼓励和支持&#xff0c;非常感谢大家的喜欢&#xff0c;所以楠姐尽自己所能马不停蹄开始第二篇的创作&#xff0c;虽迟但到~ ★…

高等数学笔记

|sinx|连续不可导 只要在x0处存在极限且极限等于f(x0)则函数在此处连续 如果某点可导则左右导数应该相等&#xff08;可导一定连续&#xff0c;连续不一定可导&#xff09; 双曲函数的由来 塞入dx 莱布尼茨公式 sin(nx)的k次导n^k*sin(nxkΠ/2) 注意符号&#xff01; 二阶导公…

实时操作系统Freertos开坑学习笔记:(五):任务调度和时间片调度

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、任务调度1.开启任务调度器函数2.启动第一个任务 二、任务切换的原理三、时间片调度1.基本概念2.看一个实际例程①我们设置滴答定时器中断时间为50ms&#x…

低代码平台:IVX 重新定义编程

目录 &#x1f36c;一、写在前面 &#x1f36c;二、低代码平台是什么 &#x1f36c;三、为什么程序员和技术管理者不太可能接受“低代码”平台&#xff1f; &#x1f36d;1、不安全&#xff08;锁定特性&#xff09; &#x1f36d;2、不信任 &#x1f36c;四、IVX低代码平台 &a…

Vue3数值动画(NumberAnimation)

效果如下图&#xff1a;在线预览 APIs 参数说明类型默认值必传from数值动画起始数值number0falseto数值目标值number1000falseduration数值动画持续时间&#xff0c;单位msnumber3000falseautoplay是否自动开始动画booleantruefalseprecision精度&#xff0c;保留小数点后几位…

vue响应式详解

1. 响应式的定义 我们都知道&#xff0c;vue是基于javascript的&#xff0c;那我们使用一段javascript代码来描述响应式 let a 1,b 1,c; c a b; console.log(c) // 输出 2 // 改变 a的值 a 3; // 重新给c赋值 即把 c a b; 再执行一遍c的值才能变为 4 // c a b; // …