$rootScope.clearElementError = function (element) {
if (!element || !element.$name) {
return;
}
if (element.$error) {
var errors = element.$error;
for (var error in errors) {
element.$setValidity(error, true);
}
}
};
$rootScope.clearElement = function (element) {
if (!element || !element.$name) {
return;
}
$rootScope.clearElementError(element);
element.$setViewValue(undefined);
element.$commitViewValue();
element.$setPristine();
element.$render();
};
$rootScope.clearForm = function (form) {
if (!form) return true;
for (var attr in form) {
var element = form[attr];
if (!element || !element.$name) {
continue;
}
$rootScope.clearElement(element);
}
form.$setPristine();
};
如果表单里面有某个元素有唯一性等需要请求后端的验证,需要在directive里设置uniqueValidate函数
例如:
<input email-unique-validator />
main.directive('emailUniqueValidator', ['returnCodeService', function (returnCodeService) {
//验证登录用户:使用的电子邮件格式、工号格式
var WorkerEmailExistUrl = rootPath + '/pdri/prms/openapisys/v101/account/emailExist/:email';
var WorkerEmailExistUrlM = rootPath + '/pdri/prms/openapisys/v101/account/emailExist/:workerId/:email';
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ctrl) {
ctrl.uniqueValidate = function(success, faild) {
var workerId = (element && element[0]) ? element[0].getAttribute('email-unique-validator') : null;
scope.uniqueValidate(ctrl, workerId ? WorkerEmailExistUrlM : WorkerEmailExistUrl, {email: ctrl.$viewValue, workerId: workerId}, null, success, faild);
};
element.bind('blur', function (event) {
var form = null;
var value = element.val();
value = value ? value.trim() : value;
//输入值需要符合,电子邮件和电话号码格式/^[1-9]{1}[0-9]*/ ^(?:13\d|15[89])-?\d{8}$
if (((form = angular.element(event.currentTarget.form).controller('form')) && form.validating === true)
|| !(value && scope.regular.EMAIL.test(value))) {
return;
}
ctrl.uniqueValidate(null);
})
}
}
}
]);
调用:
$scope.validatForm($scope.modifyUserInfoForm, function () {
dosometh...
}, function () {
dosometh...
});
// 封装get请求
var getHttpResolver = function (url, params, $resource, $q) {
var http = $resource(url, {}, {
get: {
method: 'GET',
transformRequest: function (data) {
return angular.toJson(data);
},
transformResponse: function (data) {
return angular.fromJson(data);
},
headers: {
'Cache-Control': 'no-cache',
'Pragma': 'no-cache'
}
}
});
var methodName = function (params) {
var deferredObj = $q.defer();
http.get(params, function (data) {
deferredObj.resolve(data);
}, function (err) {
deferredObj.reject(err);
});
return deferredObj.promise;
};
return methodName(params);
};
$rootScope.uniqueValidate = function (ngModel, url, params, custom, success, faild) {
getHttpResolver(url, params, $resource, $q).then(
function (data) {
returnCodeService.processCode(data.errorCode, function () {
if ((angular.isFunction(custom) && !custom(data)) || data.data) {
ngModel.$setValidity('unique', false);
if (angular.isFunction(faild)) faild();
} else {
ngModel.$setValidity('unique', true);
ngModel.$setValidity('errorCodeException', true);
ngModel.$setValidity('connectionException', true);
if (angular.isFunction(success)) {
success();
}
}
}, function () {
ngModel.$setValidity('errorCodeException', false);
//并绑定一次性事件,元素值改变时去掉“需要字符”的错误
angular.element(document.getElementsByName(ngModel.$name)[0]).one('change', function (event) {
angular.element(event.currentTarget).controller('ngModel').$setValidity('errorCodeException', true);
})
if (angular.isFunction(faild)) faild();
});
},
function (error) {
ngModel.$setValidity('connectionException', false);
//并绑定一次性事件,元素值改变时去掉“需要字符”的错误
angular.element(document.getElementsByName(ngModel.$name)[0]).one('change', function (event) {
angular.element(event.currentTarget).controller('ngModel').$setValidity('connectionException', true);
})
if (angular.isFunction(faild)) faild();
}
);
}
$rootScope.validatForm = function (form, success, faild) {
if (!form || !form.$name || form.validating) return true;
console.log('validatForm:' + form.$name);
form.$commitViewValue();
form.validating = true;
var elements = [];
//为了保证元素顺序和html里面顺序一致,先得到原生的form对象,然后循环生成angular对象
var fs = document.getElementsByName(form.$name)[0];
for (var i = 0, j = fs.length; i < j; i++) {
var obj = angular.element(fs[i]).controller('ngModel');
if (!obj || !obj.$name) {
continue;
}
elements.push(obj);
}
$rootScope.validatElement(elements, function () {
if (angular.isFunction(success)) {
success();
}
form.validating = false;
}, function () {
if (angular.isFunction(faild)) {
faild();
}
form.validating = false;
});
};
$rootScope.validatElement = function (elements, success, faild) {
var element = elements ? elements[0] : null;
if (element && element.$name) {
$rootScope.clearElementError(element);
element.$validate();
var isValid = false;
if (element && element.$invalid) { //验证不通过
} else if (!element.$invalid && (element.$modelValue === undefined || element.$modelValue === null || element.$modelValue === '')) { //验证通过,且值为空
//需求:元素本身不用添加required验证,等到提交的时候再去判断
//获取该元素的元素dom对象
var dom = document.getElementsByName(element.$name)[0];
//判断是否允许为空
var allowEmpty = dom.getAttribute('allow-empty');
if (allowEmpty !== 'true') {
//如果不允许为空,则设置“需要字符”的错误
element.$setValidity('required', false);
//并绑定一次性事件,元素值改变时去掉“需要字符”的错误
angular.element(dom).one('change', function (event) {
angular.element(event.currentTarget).controller('ngModel').$setValidity('required', true);
})
} else {
isValid = true;
}
} else {
isValid = true;
}
elements.splice(0, 1);
if (isValid) {
if (angular.isFunction(element.uniqueValidate)) {
element.uniqueValidate(function () {
$rootScope.validatElement(elements, success, faild);
}, function () {
for (var i = 0, j = elements.length; i < j; i++) {
$rootScope.clearElementError(elements[i]);
}
faild();
document.getElementsByName(element.$name)[0].focus();
});
} else {
$rootScope.validatElement(elements, success, faild);
}
} else {
if (angular.isFunction(faild)) {
faild();
}
for (var i = 0, j = elements.length; i < j; i++) {
$rootScope.clearElementError(elements[i]);
}
element.$setDirty();
document.getElementsByName(element.$name)[0].focus();
console.log('validatElement:' + "[" + element.$name + ":" + angular.toJson(element.$error) + "]");
return false;
}
} else {
if (angular.isFunction(success)) {
success();
}
return true;
}
}
/**
* Placeholder for non-HTML5 browsers ... specifically IE8 and IE9, but also
* works with Firefox 3 and possibly others.
*
* Always toggles on/off the placeholder class (default is "placeholder").
* Shims in the visual effects for older IE.
*
* Quick Usage:
*
* <input ng-model="xyz" placeholder="Enter Value" />
*
* <textarea ng-model="xyz" placeholder="Enter Value"
* placeholder-class="placeholder"></textarea>
*
* Styling:
*
* Browsers still use specific placeholder selectors. IE8 and 9 can now style
* the text with a `placeholder` class.
*
* .placeholder { color: red; }
*
* @link https://github.com/tests-always-included/angular-placeholder
* @license MIT
*/
/*global angular*/
(function (undef) {
"use strict";
var propName, needsShimByNodeName;
propName = 'placeholder';
needsShimByNodeName = {};
angular.module("taiPlaceholder", []).directive("placeholder", [
"$document",
"$timeout",
function ($document, $timeout) {
if ('placeholder' in document.createElement('input')) return {};
// Determine if we need to perform the visual shimming
angular.forEach([ 'INPUT', 'TEXTAREA' ], function (val) {
needsShimByNodeName[val] = $document[0].createElement(val)[propName] === undef;
});
/**
* Determine if a given type (string) is a password field
*
* @param {string} type
* @return {boolean}
*/
function isPasswordType(type) {
return type && type.toLowerCase() === "password";
}
return {
require: "^ngModel",
restrict: "A",
link: function ($scope, $element, $attributes, $controller) {
/*jslint unparam:true*/
var className, needsShim, text;
text = $attributes[propName]; if (!text) return;
className = $attributes[propName + "Class"] || propName;
needsShim = needsShimByNodeName[$element[0].nodeName];
var isPwd = isPasswordType($element.prop("type"));
// On blur, check the value. If nothing is entered then
// add the placeholder class and text.
$element.bind("blur", function () {
var currentValue;
currentValue = $element.val();
if (!currentValue) {
if (isPwd) $element.attr('type', 'text');
$element.addClass(className);
if (needsShim) {
/* Add a delay so the value isn't assigned to
* scope. Issue #9
*/
$timeout(function () {
$element.val(text);
}, 1);
}
}
});
// When focused, check if the field has the placeholder
// class. If so, wipe the field out.
$element.bind("focus", function () {
if (needsShim && $element.hasClass(className)) {
$element.val("");
}
$element.removeClass(className);
if (isPwd) $element.attr('type', 'password');
});
if (needsShim) {
// This determines if we show placeholder text or not
// when there was a change detected on scope.
$controller.$formatters.unshift(function (val) {
// When there is a value, this is not a placeholder.
if (val) {
$element.removeClass(className);
return val;
}
if (isPwd) $element.attr('type', 'text');
$element.addClass(className);
$timeout(function () {
$element.val(text);
}, 1);
return null;
});
}
}
};
}
]);
}());