我正在用 Angular 编写一个相当复杂的搜索表单。
该表单分为多个部分 - 您可以按 ID、URL、文本字符串或位置进行搜索。当您同时按文本字符串和位置搜索时,我需要验证您是否一起提交了纬度和经度。
换句话说,通过文本字符串搜索就可以了。按纬度/经度搜索就可以了。按文本字符串和纬度搜索但忽略经度是不行的。
只要有可能,我都会使用 HTML5 和 Angular Directive(指令)来验证各个字段的内容,但我尝试通过使用范围观察器、查看表单对象并使用 来验证特定的值组合$setValidity()
如果我发现当前搜索模式与特定字段组合不兼容。
我当前的问题是,一旦我使用过 $setValidity()
一次,验证状态就会“卡住”。当用户退出 'textOrLocation'
搜索模式时,我想让 Angular 返回到其默认验证行为。我不明白为什么它不这样做 - 在检查表单处于 'textOrLocation'
模式后,我仅在范围更改时调用 $setValidity()
。
Javascript:
$scope.search = {
mode: 'id'
};
$scope.$watch(textOrLocationValid, function() {});
function textOrLocationValid() {
var usingTextOrLocation = $scope.search.mode == 'textOrLocation';
if (usingTextOrLocation) {
var textModel = $scope.form.searchText || {},
textValid = textModel.$valid,
textValue = textModel.$modelValue,
latModel = $scope.form.searchLat || {},
latValid = latModel.$valid,
latValue = latModel.$modelValue,
lngModel = $scope.form.searchLng || {},
lngValid = lngModel.$valid,
lngValue = lngModel.$modelValue,
formValid = (textValid && latValid && lngValid) && // No invalid fields
((latValue && 1 || 0) + (lngValue && 1 || 0) != 1) && // Either both lat and long have values, or neither do
(textValue || latValue); // Either text or location are filled out
if (formValid) {
// Explicitly set form validity to true
$scope.form.$setValidity('textOrLocation', true);
} else {
// Explicitly set form validity to false
$scope.form.$setValidity('textOrLocation', false);
}
}
}
HTML
<form name="form">
<div ng-if="search.mode == 'id'">
<input type="text" name="searchId" required>
</div>
<div ng-if="search.mode == 'textOrLocation'">
<input type="text" name="searchText">
<input type="number" name="searchLat" min="-90" max="90" step="0.000001">
<input type="number" name="searchLng" min="-180" max="180" step="0.000001">
</div>
<button ng-disabled="form.$invalid">Submit</button>
</form>
最佳答案
我的理解是,因为该函数正在被监视,所以实际上 Angular 在每次摘要期间都会定期对其进行评估。一个简单的解决方案可能是当该特定表单未处于焦点时将 textOrLocation 的有效性设置为 true。这将允许按钮状态取决于 id 表单中字段的有效性。
function textOrLocationValid() {
var usingTextOrLocation = $scope.search.mode == 'textOrLocation';
if (usingTextOrLocation) {
var textModel = $scope.form.searchText || {},
textValid = textModel.$valid,
textValue = textModel.$modelValue,
latModel = $scope.form.searchLat || {},
latValid = latModel.$valid,
latValue = latModel.$modelValue,
lngModel = $scope.form.searchLng || {},
lngValid = lngModel.$valid,
lngValue = lngModel.$modelValue,
formValid = (textValid && latValid && lngValid) && // No invalid fields
((latValue && 1 || 0) + (lngValue && 1 || 0) != 1) && // Either both lat and long have values, or neither do
(textValue || latValue); // Either text or location are filled out
if (formValid) {
// Explicitly set form validity to true
$scope.form.$setValidity('textOrLocation', true);
} else {
// Explicitly set form validity to false
$scope.form.$setValidity('textOrLocation', false);
}
}
else{
// Explicitly set form validity to true because form is not active
$scope.form.$setValidity('textOrLocation', true);
}
}
关于javascript - 在表单级别使用 $setValidity 后,有效性停留在 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34424520/