javascript - 在表单级别使用 $setValidity 后,有效性停留在 false

标签 javascript angularjs forms validation

我正在用 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/

相关文章:

javascript - 传单.js : Add custom text to layers control using CSS?

javascript - 如何获取调用表单的按钮

javascript - 在 AngularJS 指令中处理范围值的惯用方法是什么?

javascript - 在模型更改之前编译 Angular 不起作用

javascript - 如何防止选择表单被更改,直到 Vue 中的对话框完成

javascript - __doPostBack 在 safari 或 firefox 中不起作用,在 IE 中起作用

javascript - Bootstrap 2 Carousel 循环一次然后停止

javascript - 在文本字段之一上按 Enter 键时, Angular ngsubmit() 指令不会提交

c# - 动态(JS)表单控件: How to read content?

php - Yii2 形式的关系属性