Javascript 使用angularjs处理三部分日期字段验证
我需要在angular js中验证一个由三部分组成的日期字段。我已经创建了一个自定义验证函数,但是在设计字段如何更新彼此状态的逻辑时遇到了问题 我如何才能让所有三个表单字段唱出同一首赞美诗,并根据其他字段显示其有效或无效状态 这是小提琴: 和代码:Javascript 使用angularjs处理三部分日期字段验证,javascript,angularjs,Javascript,Angularjs,我需要在angular js中验证一个由三部分组成的日期字段。我已经创建了一个自定义验证函数,但是在设计字段如何更新彼此状态的逻辑时遇到了问题 我如何才能让所有三个表单字段唱出同一首赞美诗,并根据其他字段显示其有效或无效状态 这是小提琴: 和代码: <div ng-app="myApp" ng-controller="myCtrl"> <form action="" name="myForm"> <div class="date-group"
<div ng-app="myApp" ng-controller="myCtrl">
<form action="" name="myForm">
<div class="date-group">
<input type="text" name="day" ng-model="day" ng-valid-func="validator" />
<input type="text" name="month" ng-model="month" ng-valid-func="validator" />
<input type="text" name="year" ng-model="year" ng-valid-func="validator" />
</div>
</form>
</div>
而且
input.ng-invalid{
background-color: #fdd !important;
}
input.ng-valid{
background-color: #dfd !important;
}
input{
display: inline;
width: 3em;
}
var app = angular.module('myApp', [])
var myCtrl = function($scope){
$scope.day = "01"
$scope.month = "01"
$scope.year = "2000"
$scope.validator = function(val){
var day = $('[name=day]').val()
var month = $('[name=month]').val()
var year = $('[name=year]').val()
var d = new Date([year,month,day].join('-'))
console.log(d, [year,month,day].join('-'))
return d > new Date('2000-01-01')
}
}
app.directive('ngValidFunc', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
if (attrs.ngValidFunc && scope[attrs.ngValidFunc] && scope[attrs.ngValidFunc](viewValue, scope, elm, attrs, ctrl)) {
ctrl.$setValidity('custom', true);
} else {
ctrl.$setValidity('custom', false);
}
return elm.val()
});
}
};
});
实际上,您最好只使用
input type=“number”
和max
和min
验证器,并添加调用函数更新日期的ng change
指令
由于如果输入内容无效,则不会触发更改,因此您永远不会得到“错误”日期:
但是使用月和日的文本框可能是不好的解决方案,因为这将变得更加复杂,确保日值符合犹太标准。(以二月和闰年为例)。对于整个解决方案,我建议至少在几天内使用下拉列表,也可能在一个月内使用下拉列表。。。因为有一组固定的结果是必需的,并且您可以根据月份选项的值显示或隐藏日期选项
下面是一个例子:
<form name="myForm">
<input type="number" name="year" ng-model="year" min="2000" ng-change="updateDate()"/>
<select name="month" ng-model="month" ng-change="updateDate()">
<option value="1">Jan</option>
<option value="2">Feb</option>
<option value="3">Mar</option>
<option value="4">Apr</option>
<option value="5">May</option>
<option value="6">Jun</option>
<option value="7">Jul</option>
<option value="8">Aug</option>
<option value="9">Sep</option>
<option value="10">Oct</option>
<option value="11">Nov</option>
<option value="12">Dec</option>
</select>
<select name="day" ng-model="day" ng-change="udpateDate()">
<option>1</option>
<option>2</option>
<option>3</option>
<!-- ... SNIP!... -->
<option>27</option>
<option>28</option>
<option ng-show="month != 2 || !(year % 4)")>
29
</option>
<option ng-show="month != 2">
30
</option>
<option ng-show="month == 1 || month == 3 || month == 5 || month == 7 ||
month == 8 || month == 10 || month == 12">
31
</option>
</select>
<p>
{{date | date: 'yyyy-MMM-dd'}}
</p>
</form>
简
二月
破坏
四月
也许
六月
七月
八月
九月
十月
十一月
12月
1.
2.
3.
27
28
29
30
31
{{date}日期:'yyyy-MMM-dd'}
但是,为什么不动态创建这些选择呢?
您能否动态创建上述选择?当然值得吗?大概可能不会。只需30秒即可将选项与show/hyde逻辑一起键入
在上述两种情况下,您只需验证2001年的年度验证:
<span ng-show="myForm.year.$error.min">Must be after January 1, 2001</span>
必须在2001年1月1日之后
我也在寻找AngularJS的三部分日期字段验证,以下是我所做的(为我工作)
HTML:
日期(年月日):
-
-
必修的!
太短了!
不是有效日期!
提交
脚本:
function Controller ($scope) {
$scope.notValidDate = false;
$scope.somefuncion = function(event) {
if ($scope.myForm.$valid) {
alert("Form is working as expected");
return true;
}
else
{
alert("Something is not correct");
return false;
}
};
$scope.validateDOB = function(mm,dd,yyyy)
{
var flag = true;
var month = mm;
var date = dd;
var year = yyyy;
if(month == null || date == null || year == null || month.length != 2 || date.length!= 2 || year.length!= 4)
flag = false;
if(month < 1 || month > 12)
flag = false;
if(year < 1900 || year > 2100)
flag = false;
if(date < 1 || date > 31)
flag = false;
if((month == 04 || month == 06 || month == 9 || month == 11) && (date >= 31))
flag = false;
if(month == 02)
{
if(year % 4 != 0)
{
if(date > 28)
flag = false;
}
if(year % 4 == 0)
{
if(date > 29)
flag = false;
}
}
var dob = new Date();
dob.setFullYear(year, month - 1, date);
var today = new Date();
if(dob > today)
flag = false;
if(flag)
{
$scope.notValidDate = false;
$scope.myForm.$valid = true;
}
else
{
$scope.notValidDate = true;
$scope.myForm.$valid = false;
form.partnerDOBmm.focus();
}
}
}
angular.module('testModule', [])
.directive('onlyDigits', function () {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ngModel) {
if (!ngModel) return;
ngModel.$parsers.unshift(function (inputValue) {
var digits = inputValue.replace(/[^\d]/g, "");
ngModel.$viewValue = digits;
ngModel.$render();
return digits;
});
}
};
});
功能控制器($scope){
$scope.notValidDate=false;
$scope.someFunction=函数(事件){
如果($scope.myForm.$valid){
警报(“表单按预期工作”);
返回true;
}
其他的
{
警惕(“某些东西不正确”);
返回false;
}
};
$scope.validateDOB=函数(月、日、年)
{
var标志=真;
var月=mm;
var日期=dd;
变量年份=yyy;
如果(月==null | | |日期==null | | |年==null | | |月.长!=2 | | |年.长!=4)
flag=false;
如果(月<1 | |月>12)
flag=false;
如果(年份<1900 |年份>2100)
flag=false;
如果(日期<1 | |日期>31)
flag=false;
如果((月==04 | |月==06 | |月==9 | |月==11)和&(日期>=31))
flag=false;
如果(月份==02)
{
如果(年份%4!=0)
{
如果(日期>28)
flag=false;
}
如果(第%4年==0)
{
如果(日期>29)
flag=false;
}
}
var dob=新日期();
dob.setFullYear(年、月-1日);
var today=新日期();
如果(dob>今天)
flag=false;
国际单项体育联合会(旗)
{
$scope.notValidDate=false;
$scope.myForm.$valid=true;
}
其他的
{
$scope.notValidDate=true;
$scope.myForm.$valid=false;
form.partnerdomm.focus();
}
}
}
角度.module('testModule',[])
.directive('onlyDigits',函数(){
返回{
限制:“A”,
要求:“?ngModel”,
链接:功能(范围、元素、属性、模型){
如果(!ngModel)返回;
ngModel.$parsers.unshift(函数(inputValue){
var digits=inputValue.replace(/[^\d]/g,“”);
ngModel.$viewValue=位数;
ngModel.$render();
返回数字;
});
}
};
});
请随意即兴回答,希望您可以在“validateDOB”函数中使用“else”我遇到了一个非常类似的问题。问题是,您可能不想检查字段之间的关系。如果你这样做,很难确定日期是否确实有效,例如如果不是2月30日。您要做的是通过中间元素检查整个日期 作为旁注,根据设计,控制器不应参与此类活动。验证应该在指令级别上进行,所以它是可重用的,并且与Angular一致,这给了您验证程序链的好处。例如,如果您只需要检查一个有效日期,但在另一个示例中,您需要检查出生日期的年龄,那么您将最终“弄湿”您的代码:) 我提出了一个相当简单的解决方案,非常符合角度哲学。诀窍是使用中间表单元素(例如隐藏输入),它将所有三个下拉列表汇集在一起,并一次性对整个日期执行验证 以下是HTML,用于设置焦点:
<form name="dateForm" novalidation>
<input type="hidden"
ng-model="modelDate"
date-type-multi="viewDate"
ng-init="viewDate = {}"
class="form-control"
/>
<select ng-model="viewDate.day">
<option value="">select day</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
<select ng-model="viewDate.month">
<option value="">select month</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
</select>
<select ng-model="viewDate.year">
<option value="">select year</option>
<option value="1981">1981</option>
<option value="1982">1982</option>
<option value="1983">1983</option>
<option value="1984">1984</option>
<option value="1985">1985</option>
<option value="1986">1986</option>
<option value="1987">1987</option>
<option value="1988">1988</option>
<option value="1989">1989</option>
<option value="1990">1990</option>
<option value="1991">1991</option>
<option value="1992">1992</option>
</select>
</form>
在指令上设置低优先级是很重要的,因为这样解析器作为第一个启动(与格式化程序的顺序相反),该字段上的其他验证器将获得解析日期
你可以在这里玩:
我在这里详细描述了思考过程:
function Controller ($scope) {
$scope.notValidDate = false;
$scope.somefuncion = function(event) {
if ($scope.myForm.$valid) {
alert("Form is working as expected");
return true;
}
else
{
alert("Something is not correct");
return false;
}
};
$scope.validateDOB = function(mm,dd,yyyy)
{
var flag = true;
var month = mm;
var date = dd;
var year = yyyy;
if(month == null || date == null || year == null || month.length != 2 || date.length!= 2 || year.length!= 4)
flag = false;
if(month < 1 || month > 12)
flag = false;
if(year < 1900 || year > 2100)
flag = false;
if(date < 1 || date > 31)
flag = false;
if((month == 04 || month == 06 || month == 9 || month == 11) && (date >= 31))
flag = false;
if(month == 02)
{
if(year % 4 != 0)
{
if(date > 28)
flag = false;
}
if(year % 4 == 0)
{
if(date > 29)
flag = false;
}
}
var dob = new Date();
dob.setFullYear(year, month - 1, date);
var today = new Date();
if(dob > today)
flag = false;
if(flag)
{
$scope.notValidDate = false;
$scope.myForm.$valid = true;
}
else
{
$scope.notValidDate = true;
$scope.myForm.$valid = false;
form.partnerDOBmm.focus();
}
}
}
angular.module('testModule', [])
.directive('onlyDigits', function () {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ngModel) {
if (!ngModel) return;
ngModel.$parsers.unshift(function (inputValue) {
var digits = inputValue.replace(/[^\d]/g, "");
ngModel.$viewValue = digits;
ngModel.$render();
return digits;
});
}
};
});
<form name="dateForm" novalidation>
<input type="hidden"
ng-model="modelDate"
date-type-multi="viewDate"
ng-init="viewDate = {}"
class="form-control"
/>
<select ng-model="viewDate.day">
<option value="">select day</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
<select ng-model="viewDate.month">
<option value="">select month</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
</select>
<select ng-model="viewDate.year">
<option value="">select year</option>
<option value="1981">1981</option>
<option value="1982">1982</option>
<option value="1983">1983</option>
<option value="1984">1984</option>
<option value="1985">1985</option>
<option value="1986">1986</option>
<option value="1987">1987</option>
<option value="1988">1988</option>
<option value="1989">1989</option>
<option value="1990">1990</option>
<option value="1991">1991</option>
<option value="1992">1992</option>
</select>
</form>
angular.module('dateApp', []).
directive('dateTypeMulti', function() {
return {
priority: -1000,
require: 'ngModel',
link: function(scope, elem, attrs, ngModel) {
ngModel.$render = function() {
angular.extend(scope.$eval(attrs.dateTypeMulti), ngModel.$viewValue);
};
scope.$watch(attrs.dateTypeMulti, function(viewValue) {
ngModel.$setViewValue(viewValue);
}, true);
ngModel.$formatters.push(function(modelValue) {
if (!modelValue) return;
var parts = String(modelValue).split('/');
return {
year: parts[0],
month: parts[1],
day: parts[2]
};
});
ngModel.$parsers.unshift(function(viewValue) {
var isValid = true,
modelValue = '',
date;
if (viewValue) {
date = new Date(viewValue.year, viewValue.month - 1, viewValue.day);
modelValue = [viewValue.year, viewValue.month, viewValue.day].join('/');
if ('//' === modelValue) {
modelValue = '';
} else if (
date.getFullYear() != viewValue.year ||
date.getMonth() != viewValue.month - 1 ||
date.getDate() != viewValue.day) {
isValid = false;
}
}
ngModel.$setValidity('dateTypeMulti', isValid);
return isValid ? modelValue : undefined;
});
}
};
});
@validateDateDirective = ->
require: "ngModel"
link: (scope, elem, attr, ngModel) ->
# Get the base model name without the _day _month _year appended
# e.g for field 'birth_date_year', this would equal 'birth_date'
modelName = attr.ngModel.replace('_day', '').replace('_month', '').replace('_year', '')
# use base model name to watch all models in target fieldset
scope.$watchCollection '['+modelName+'_day, '+modelName+'_month, '+modelName+'_year]', ->
# Set global value
value = [scope.$eval(modelName+'_year'),
scope.$eval(modelName+'_month'),
scope.$eval(modelName+'_day')]
# << do your validation here >>