一. 样例介绍

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

HarmonyOS实现表单页面的输入,必填校验和提交的更多相关文章

  1. AngularJS 表单验证手机号(非必填)

    代码: <form ng-app="myApp" ng-controller="validateCtrl" name="myForm" ...

  2. Dynamics 365 CE命令栏按钮点击后刷新表单页面方法

    微软动态CRM专家罗勇 ,回复326或者20190428可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me! Dynamics 365 Customer Engagement ...

  3. HTML 表单元素、 输入类型、Input 属性

    <input> 元素 最重要的表单元素是 <input> 元素. <input> 元素根据不同的 type 属性,可以变化为多种形态. 注释:下一章讲解所有 HTM ...

  4. 开发日志系列:一个表单页面的呈现与提交(一)——JSON的操作

    JSON操作 引子 最近在做一个表单页面,大概是这个样子的 这里打算用一个JSON存储所有的信息,我们可以理解为,所有东西都存在一个字符串里面.方便,快捷,易读,数据库操作也方便了.甚至,可以将很多不 ...

  5. Form提交表单页面不跳转

    1.设计源码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. ...

  6. PHP 表单和用户输入讲解

    PHP 表单和用户输入 PHP 中的 $_GET 和 $_POST 变量用于检索表单中的信息,比如用户输入. PHP 表单处理 有一点很重要的事情值得注意,当处理 HTML 表单时,PHP 能把来自 ...

  7. 基于react hooks,zarm组件库配置开发h5表单页面

    最近使用React Hooks结合zarm组件库,基于js对象配置方式开发了大量的h5表单页面.大家都知道h5表单功能无非就是表单数据的收集,验证,提交,回显编辑,通常排列方式也是自上向下一行一列的方 ...

  8. C# Winform 通过FlowLayoutPanel及自定义的编辑控件,实现快速构建C/S版的编辑表单页面

    个人理解,开发应用程序的目的,不论是B/S或是C/S结构类型,无非就是实现可供用户进行查.增.改.删,其中查询用到最多,开发设计的场景也最为复杂,包括但不限于:表格记录查询.报表查询.导出文件查询等等 ...

  9. Winform 通过FlowLayoutPanel及自定义的编辑控件,实现快速构建C/S版的编辑表单页面 z

    http://www.cnblogs.com/zuowj/p/4504130.html 不论是B/S或是C/S结构类型,无非就是实现可供用户进行查.增.改.删,其中查询用到最多,开发设计的场景 也最为 ...

  10. SharePoint Designer定制MOSS/WSS表单页面

    转:http://blog.csdn.net/yl_99/article/details/7087897 方法一.使用SharePoint Designer配合enderingTemplate文件来定 ...

随机推荐

  1. 【Azure API 管理】APIM服务资源删除后,为什么不能马上创建相同名称的APIM服务呢?

    问题描述 使用Azure APIM服务,在删除旧资源准备新建相同名称的新APIM服务时,尝试多次都是出现"指定的服务名称已正在使用"错误.但实际上同名称的服务已经被删除.为什么多次 ...

  2. 【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常

    Azure Spring Cloud 是什么? 借助 Azure Spring Cloud,可以轻松地将 Spring Boot 微服务应用程序部署到 Azure,不需更改任何代码. 该服务管理 Sp ...

  3. C++ STL 容器-array类型

    C++ STL 容器-array类型 array是C++11STL封装的数组,内存分配在栈中stack,绝对不会重新分配,随机访问 创建和初始化 // 下面的等同于int a[10]; std::ar ...

  4. 解决windows11远程连接阿里云Centos7

    本地连接CentOs7时报错   Permission denied (publickey,gssapi-keyex,gssapi-with-mic). 网上大部分说的是去修改 vim /etc/ss ...

  5. 50HZ陷波器的原理和实物开发设计

    原理     陷波滤波器指的是一种可以在某一个频率点迅速衰减输入信号,以达到阻碍此频率信号通过的滤波效果的滤波器.陷波滤波器属于带阻滤波器的一种,只是它的阻带非常狭窄,起阶数必须是二阶(含二阶)以上. ...

  6. 基于六轴传感器MPU6050的物体移动监测报警系统

    一 系统简介 1.简介 MPU-60x0 是全球首例 9 轴运动处理传感器.它集成了 3 轴MEMS陀螺仪,3 轴MEMS加速度计,以及一个可扩展的数字运动处理器 DMP(Digital Motion ...

  7. hibernate之createQuery与createSQLQuery

    信息: java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.miracle.dm.doc.catalog.m ...

  8. 单体JOB向分布式JOB迁移案例

    一.背景 1.1前言 相信大家在工作中多多少少都离不开定时任务吧,每个公司对定时任务的具体实现都不同.在一些体量小的公司或者一些个人独立项目,服务可能还是单体的,并且在服务器上只有一台实例部署,大多数 ...

  9. Java博客大汇总

    目录介绍 01.Java基础[30篇] 02.面向对象[15篇] 03.数据结构[27篇] 04.IO流知识[11篇] 05.线程进程[9篇] 06.虚拟机[12篇] 07.类的加载[7篇] 08.反 ...

  10. uni-app攻略:如何对接驰腾打印机

    一.引言 在当前的移动开发生态中,跨平台框架如uni-app因其高效.灵活的特点受到了开发者们的青睐.同时,随着物联网技术的飞速发展,智能打印设备已成为许多业务场景中不可或缺的一环.今天,我们就来探讨 ...