【angular5项目积累总结】表单复杂校验
view

code
form.css
:host {
display: flex;
width: 100%;
height:100%;
border-left:1px solid #ccc;
}
.invalid-box {
border: 1px solid #a94442;
}
.invalid-error-tip {
color: #a94442;
}
.select-box {
width:308px;
height: 22px;
}
label {
line-height:20px;
}
.note {
color:#bbb;
font-size:12px;
}
.small-input {
width: 80%;
height: 19px;
line-height: 19px;
}
.small-input :-moz-placeholder,
.small-input :-ms-input-placeholder,
.small-input ::-webkit-input-placeholder {
line-height: 10px;
font-size: 10px;
}
.sm-textBox-wrapper {
width: 80%;
}
.sm-textBox-wrapper [placeholder] {
text-overflow: ellipsis;
font-style: italic;
}
.sm-textBox-wrapper .azc-input {
box-sizing: border-box;
font-size: 12px;
outline:;
width: 100%;
}
.error-input {
border-color: #e81123 !important;
border-style: solid;
border-width: 1px;
}
.edit-input-wrapper {
display: inline-block;
float: left;
}
.error-icon {
height: 19px;
width: 10px;
line-height: 19px;
}
.tootip-balloon-w {
width: 115px;
}
.fxc-grid2.fxc-grid-sorting a.fxc-sortable {
height:35px;
}
form.html
<panel-component [menuItems]="menuItems" headerTitle="创建部署" initWidth="400px" (closeEvent)="onClose()">
<form style="margin:25px; width: 90%;height: 100%;overflow-x: hidden;" #dpyForm="ngForm">
<div style="width:90%;padding:5px 3px; font-size:12px;">
<div style="padding-top:4px;">
<label>App ID:</label>
<span>{{currApp.name}}</span>
</div>
</div>
<div style="width:90%;padding:5px 3px; font-size:12px;">
<div style="padding-top:4px;">
<label>Package ID:</label>
<span>{{currPkg.version}}</span>
</div>
</div>
<div style="width:90%;padding:5px 3px; font-size:12px;">
<div class="azc-required-anchor" style="float:left;padding-top:4px;">
<svg xmlns="http://www.w3.org/2000/svg" class=" fxs-portal-svg" role="presentation" aria-hidden="true" viewBox="0 0 6 6" focusable="false" xmlns:NS1="" NS1:xmlns:svg="http://www.w3.org/2000/svg">
<g>
<path class="msportalfx-svg-c22" d="M 3.543 2.352 l 2.08 -0.716 L 6 2.687 l -2.076 0.675 L 5.21 5.158 l -0.942 0.676 l -1.242 -1.867 l -1.264 1.867 l -0.97 -0.676 l 1.305 -1.796 L 0 2.687 L 0.38 1.63 l 2.058 0.743 V 0.233 h 1.105 v 2.119 Z" />
</g>
</svg>
</div>
<div style="width:200px;float:left;padding-top:4px;">
<label>请选择级别</label>
</div>
<div style="width:90%">
<select (change)="onValid(null)" class="select-box" [(ngModel)]="currDpy.Level" required name="Level" #level="ngModel" [ngClass]="{'invalid-box': (level.invalid && (level.dirty || level.touched))||showLevelError}">
<option *ngFor="let level of lstLevel" [value]='level.Key'>{{level.Value}}</option>
</select>
<div *ngIf="(level.invalid && (level.dirty || level.touched))||showLevelError" class="invalid-error-tip">
级别为必填字段
</div>
</div>
</div>
<div style="width:90%;padding:5px 3px; font-size:12px;">
<div class="azc-required-anchor" style="float:left;padding-top:4px;">
<svg xmlns="http://www.w3.org/2000/svg" class=" fxs-portal-svg" role="presentation" aria-hidden="true" viewBox="0 0 6 6" focusable="false" xmlns:NS1="" NS1:xmlns:svg="http://www.w3.org/2000/svg">
<g>
<path class="msportalfx-svg-c22" d="M 3.543 2.352 l 2.08 -0.716 L 6 2.687 l -2.076 0.675 L 5.21 5.158 l -0.942 0.676 l -1.242 -1.867 l -1.264 1.867 l -0.97 -0.676 l 1.305 -1.796 L 0 2.687 L 0.38 1.63 l 2.058 0.743 V 0.233 h 1.105 v 2.119 Z" />
</g>
</svg>
</div>
<div style="width:200px;float:left;padding-top:4px;">
<label>端口号配置</label>
</div>
<div style="width:100%">
<!--列表信息-->
<div class="ext-hubs-browse-grid fxc-base fxs-grid-focus fxc-grid-sorting fxc-grid-scrolling fxc-grid-resizing fxs-grid-selection fxc-grid-contextMenu fxc-grid-grouping fxc-grid2 azc-control fxc-grid-verticalScroll" style="width: 100%;">
<div class="fxc-grid-container azc-br-muted">
<div class="fxc-grid-tableContainer azc-br-muted" style="padding-top: 42px;">
<div class="fxc-grid-tableScrollContainer azc-br-muted">
<table class="fxc-grid-tableHeader fxs-grid-multiselection" data-grid-activation="true">
<thead>
<tr>
<th class="fxc-grid-sorting-header fxc-grid-column-header " style="width: 21%;">
<div class="fxc-grid-header-wrapper">
<a aria-sort="none" class="fxc-sortable fxc-none">
<span class="fxc-grid-headerlabel">序号</span>
</a>
<div class="fxc-grid-resizableColumn-handle">
<div class="fxc-grid-resizableColumn-handle-line azc-bg-muted">
</div>
</div>
</div>
</th>
<th class="fxc-grid-sorting-header fxc-grid-column-header ">
<div class="fxc-grid-header-wrapper">
<a aria-sort="none" class="fxc-sortable fxc-none">
<span class="fxc-grid-headerlabel">Docker镜像</span>
</a>
<div class="fxc-grid-resizableColumn-handle">
<div class="fxc-grid-resizableColumn-handle-line azc-bg-muted">
</div>
</div>
</div>
</th>
<th class="fxc-grid-sorting-header fxc-grid-column-header ">
<div class="fxc-grid-header-wrapper">
<a aria-sort="none" class="fxc-sortable fxc-none">
<span class="fxc-grid-headerlabel">部署应用</span>
</a>
<div class="fxc-grid-resizableColumn-handle">
<div class="fxc-grid-resizableColumn-handle-line azc-bg-muted">
</div>
</div>
</div>
</th>
</tr>
</thead>
</table>
<div class="fxc-grid-tableContent" style="position: relative; overflow-x: hidden;" >
<table class="fxc-grid-full fxs-grid-multiselection" data-grid-activation="true">
<tbody class="fxc-grid-groupdata ">
<tr class="fxc-grid-row fxs-portal-focus fxs-portal-hover" *ngFor="let port of lstPorts;let i = index">
<td class="fxc-grid-cell azc-br-muted" style="width:10%">
<span class="fxc-grid-cellContent fxs-ellipsis">
<span class="msportalfx-gridcolumn-assetsvg-text">{{i}}</span>
</span>
</td>
<td class="fxc-grid-cell azc-br-muted" style="width:12%;">
<span class="fxc-grid-cellContent fxs-ellipsis">
<span class="msportalfx-gridcolumn-assetsvg-text">{{port.docker}}</span>
</span>
</td>
<td class="fxc-grid-cell azc-br-muted" style="width:20%;">
<div class="sm-textBox-wrapper" tabindex="-1">
<div class="edit-input-wrapper">
<input [(ngModel)]="port.app" (blur)="onValid(i)" (keyup)="onValid(i)" class="azc-input small-input" min="1" pattern="^[1-9]+[0-9]*$" maxlength="5" name="Ports" required type="number" placeholder="输入端口号" tabindex="0" [ngClass]="{'error-input': !port.valid}">
</div>
<div *ngIf="!port.valid" class="fxc-base azc-control azc-dockedballoon azc-dockedballoon-validation azc-bg-default fxs-bg-error error-icon" (mouseenter)="toggleBalloonTip($event,true)" (mouseleave)="toggleBalloonTip($event,false)">
<div class="azc-dockedballoon-anchor">
<span>
<svg height="100%" width="100%" aria-hidden="true" role="presentation" focusable="false">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#FxSymbol0-063"></use>
</svg>
</span>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table> </div>
</div> </div> </div>
<div [ngClass]="{'azc-balloon-hidden':!isShowBalloon}" class="azc-dockedballoon-balloon azc-dockedballoon-validation azc-bg-default fxc-base azc-control azc-balloon azc-balloon-forcedisplayblock azc-balloon-position-alternate azc-balloon-box-top tootip-balloon-w" [ngStyle]="{'top.px': balloonTop,'left.px': balloonLeft}">
<div class="azc-br-muted-80-10 azc-balloon-pointer"></div>
<div class="azc-bg-muted-80-10 fxs-text-white azc-balloon-content"><div class="azc-balloon-text">此字段为必填项且长度不超过5位的正整数</div></div>
</div>
</div> </div>
</div>
<div style="width:90%;padding:5px 3px; font-size:12px;">
<div class="azc-required-anchor" style="float:left;padding-top:4px;">
<svg xmlns="http://www.w3.org/2000/svg" class=" fxs-portal-svg" role="presentation" aria-hidden="true" viewBox="0 0 6 6" focusable="false" xmlns:NS1="" NS1:xmlns:svg="http://www.w3.org/2000/svg">
<g>
<path class="msportalfx-svg-c22" d="M 3.543 2.352 l 2.08 -0.716 L 6 2.687 l -2.076 0.675 L 5.21 5.158 l -0.942 0.676 l -1.242 -1.867 l -1.264 1.867 l -0.97 -0.676 l 1.305 -1.796 L 0 2.687 L 0.38 1.63 l 2.058 0.743 V 0.233 h 1.105 v 2.119 Z" />
</g>
</svg>
</div>
<div style="width:200px;float:left;padding-top:4px;">
<label>实例数</label>
</div>
<div style="width:90%">
<input type="number" min="1" pattern="^[1-9]+[0-9]*$" maxlength="5" (keyup)="onValid(null)" class="azc-input" style="width:305px;" [(ngModel)]="currDpy.InstanceCount" name="InstanceCount" [ngClass]="{'invalid-box': (instanceCount.invalid && (instanceCount.dirty || instanceCount.touched))||showInsCountError}" required #instanceCount="ngModel" />
<div *ngIf="(instanceCount.invalid && (instanceCount.dirty || instanceCount.touched))|| showInsCountError" class="invalid-error-tip">
实例数为必填字段且为有效数字
</div>
</div>
</div>
<div style="width:90%;padding:5px 3px; font-size:12px;">
<div style="width:100%;float:left;padding-top:4px;">
<label>描述</label>
<span class="note">(注:多个描述项之间请用英文分号“;”分隔)</span>
</div>
<div style="width:90%">
<textarea class="azc-input" style="width:305px;height:100px" [(ngModel)]="currDpy.Description" name="Description"></textarea>
</div>
</div>
</form>
</panel-component>
<router-outlet></router-outlet>
form.ts
import { Component, ViewChild} from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { AppStoreService } from '../service/appStoreService';
import { CommonService } from '../../providers/commonService';
@Component({
selector: 'deploy-page',
templateUrl: './deploy.html',
styleUrls: ['./deploy.css']
})
export class DeployPage {
@ViewChild('dpyForm') dpyForm;
constructor(
private router: Router,
private actRouter: ActivatedRoute,
private appStoreService: AppStoreService,
private comService: CommonService) {
}
currDpy: any = {
AppId: "",
PackageId:"",
Level:"",
Description: "",
InstanceCount: "",
Ports:""
};
id: string;
pkgId: any;
currApp: any = {
id: '',
name:''
};
currPkg: any = {
id: '',
version:''
};
lstPorts: any = [];
lstLevel: {} = [
{
"Key": 0,
"Value": "高"
},
{
"Key": 1,
"Value": "中"
},
{
"Key": 2,
"Value": "低"
}
];
showLevelError: boolean;
showInsCountError: boolean;
isShowBalloon: boolean = false;
balloonTop: any;
balloonLeft: any;
parentUrl: string;
menuItems: any = [
{ title: "提交", icon: "#FxSymbol0-001", event: this.onSaveDpyInfo.bind(this) }
]
ngOnInit(): void {
this.actRouter.params.subscribe((params: Params) => {
this.id = params["id"];
this.pkgId = params["pkgId"];
});
this.appStoreService.GetPkgOne(this.pkgId, (rtv) => {
this.currPkg = rtv;
rtv.ports.split(',').forEach(p => {
this.lstPorts.push({ 'docker':p,'app':'','valid':true});
});
});
this.appStoreService.GetAppOne(this.id, (rtv) => {
this.currApp = rtv;
});
this.parentUrl = "/webAppStore/" + this.id + "/version";
}
onClose() {
this.router.navigate([this.parentUrl, { id: this.id, pkgId: this.pkgId }]);
}
onValid(index: any) {
this.showLevelError = this.currDpy.Level ? false : true;
if (this.currDpy.InstanceCount && /^[1-9][0-9]{0,4}$/.test(this.currDpy.InstanceCount)) {
this.showInsCountError = false;
} else {
this.showInsCountError = true;
}
if (index && this.lstPorts[index]) {
this.validPort(this.lstPorts[index])
} else {
this.lstPorts.map(p => this.validPort(p))
}
}
validPort(port: any) {
port.app && /^[1-9][0-9]{0,4}$/.test(port.app) ? port.valid = true : port.valid = false;
}
onSaveDpyInfo() {
this.onValid(null);
let emptyItem = this.lstPorts.find(item => { return !item.app || item.valid == false });
if (this.dpyForm.form.valid && !emptyItem && this.showLevelError == false && this.showInsCountError == false) {
this.currDpy.AppId = this.currApp.id;
this.currDpy.PackageId = this.currPkg.id;
this.lstPorts.forEach(p => delete p.valid);
this.currDpy.Ports = JSON.stringify(this.lstPorts);
this.appStoreService.SaveAppDpyInfo(this.currDpy, () => {
var notifyBody = { action: 'refreshWebDpy', pkgId: this.pkgId};
this.comService.notifyOther(notifyBody);
this.router.navigate([this.parentUrl, { id: this.id, pkgId: this.pkgId }]);
});
}
}
toggleBalloonTip(event: any, isShow: boolean) {
this.isShowBalloon = isShow;
if (event) {
this.balloonLeft = event.pageX - 110;
this.balloonTop = event.pageY - 100;
event.stopPropagation();
}
}
}
【angular5项目积累总结】表单复杂校验的更多相关文章
- form表单提交校验
<form id="myForm" action="http://www.365mini.com" method="post"> ...
- Element Ui使用技巧——Form表单的校验规则rules详细说明
Element UI中对Form表单验证的使用介绍: Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item的 prop 属性设置为需校验的字段名 ...
- vue中的表单异步校验方法封装
在vue项目的开发中,表单的验证必不可少,在开发的过程中,用的是vue+iview的一套,我们知道iview的表单验证是基于async-validator,对于async-validator不熟悉的可 ...
- JS表单前台校验模板
表单校验是几乎所有WEB应用都会用到的,这里提供一种用原生JavaScript的简单前台校验 <form id="registerForm" action="&qu ...
- 表单 - Validatebox - 表单参数校验
$("input[name='username']").validatebox({ required: true,//必填 validType:'email'//要求用户名必须是一 ...
- 使用JavaScript 实现注册表单的校验
说明:在点击提交时进行表单校验,具体要求如下: 1)用户名为3~16个字符,且不能包含”@”和”#”字符: 2)密码和校验密码必须一致,且长度在8个字符到16个字符: 3)兴趣爱好至少选择一项: 4) ...
- js form表单的校验
if(!$("#form").validate().form()){ return false;} <元素 class="required">< ...
- 【angular5项目积累总结】消息订阅服务
code import { Injectable } from '@angular/core'; import { Subject } from 'rxjs/Subject'; @Injectable ...
- JavaScript:使用JavaScript 实现注册表单的校验
说明:在点击提交时进行表单校验,具体要求如下: 1)用户名为3~16个字符,且不能包含”@”和”#”字符: 2)密码和校验密码必须一致,且长度在8个字符到16个字符: 3)兴趣爱好至少选择一项: 4) ...
- Maven web项目(简单的表单提交) 搭建(eclipse)
我们将会搭建一个,基于Maven管理的,具有简单的表单提交功能的web项目,使用DAO--service--WEB三层结构,服务器使用Tomcat 1 项目基本结构的搭建 左上角File---> ...
随机推荐
- ubuntu 16.04.1 nginx彻底删除与重新安装
1.删除nginx,-purge包括配置文件 sudo apt-get --purge remove nginx 2.移除全部不使用的软件包 sudo apt-get autoremove 3.罗列出 ...
- sharepoint 2010 powershell
可参看云总的博客:http://blog.csdn.net/yun_liang1028/article/details/6419729
- C/C++,python,java,C#月经贴问题
在刚开始的时候,一直纠结于语言之争,什么什么有前途,什么什么没前途.对于什么的支持不好啦,个人信仰问题啦.什么都有. 首先最主要的一个个人观点:“语言不是老婆,不是一夫一妻制”.你可以同时拥有许多的女 ...
- 苹果appID的获取方法
1.登陆 iTunes Connect iTunes Connect 2.选择我的app 3.选择相应的应用 4.查看结果
- sql—常用函数
COUNT()函数 COUNT()函数返回匹配指定条件的行数 SQL COUNT(column_name) 语法 COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入): ...
- 动态代理方案性能对比 (CGLIB,ASSIT,JDK)
动态代理工具比较成熟的产品有: JDK自带的,ASM,CGLIB(基于ASM包装),JAVAASSIST, 使用的版本分别为: JDK-1.6.0_18-b07, ASM-3.3, CGLIB-2.2 ...
- leetcode-36-有效的数独
题目描述: 判断一个 9x9 的数独是否有效.只需要根据以下规则,验证已经填入的数字是否有效即可. 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以 ...
- sort函数详解(史上最完整QAQ)
1.sort 使用:#include <algorithm> using namespace std; 作用:排序 时间复杂度:n*lg(n) 实现原理:sort并不是简单的快速排序, ...
- 接口测试-postman,JMeter与LoadRunner比较
postman是一个谷歌出的轻量级的专门测试接口的小工具~(PS:postman包括两种:Chrome浏览器插件和postman客户端,我使用的是postman客户端)虽然不如firefox的post ...
- localStorage注册页面A注册数据在本地储存并在B页面打开
如题目的这么一个问题, A页面代码 <!DOCTYPE html> <html lang="en"> <head> <meta chars ...