触发自定义验证指令后,AngularJS ng-model 值丢失

标签 angularjs angularjs-directive angularjs-scope angular-ngmodel

我创建了一个自定义验证指令并在表单中使用它。可以正常触发,但是触发validation后,我发现模型值刚刚丢失。说我有

ng-model="project.key" 

验证后,project.key不再存在于范围内。我想不知何故我理解 AngularJS 是错误的并且做错了什么。

代码会说话。

这是我的 html 页面:
 <div class="container">
    ...
    <div class="form-group"
            ng-class="{'has-error': form.key.$invalid && form.key.$dirty}">
            <label for="key" class="col-sm-2 control-label">Key</label>
            <div class="col-sm-10">
                <input type="text" class="form-control text-uppercase" name="key"
                    ng-model="project.key" ng-model-options="{ debounce: 700 }"
                    placeholder="unique key used in url"
                    my-uniquekey="vcs.stream.isProjectKeyValid" required />
                <div ng-messages="form.key.$error" ng-if="form.key.$dirty"
                    class="help-block">
                    <div ng-message="required">Project key is required.</div>
                    <div ng-message="loading">Checking if key is valid...</div>
                    <div ng-message="keyTaken">Project key already in use, please
                        use another one.</div>
                </div>
            </div>
        </div>
    <div class="col-sm-offset-5 col-sm-10">
        <br> <a href="#/" class="btn">Cancel</a>
        <button ng-click="save()" ng-disabled="form.$invalid"
            class="btn btn-primary">Save</button>
        <button ng-click="destroy()" ng-show="project.$key"
            class="btn btn-danger">Delete</button>
    </div>
</form>

这是我的指令:
    .directive('myUniquekey', function($http) {
        return {
            restrict : 'A',
            require : 'ngModel',
            link : function(scope, elem, attrs, ctrl) {
                var requestTypeValue = attrs.myUniquekey;

                ctrl.$parsers.unshift(function(viewValue) {
                    // if (viewValue == undefined || viewValue == null
                    // || viewValue == "") {
                    // ctrl.$setValidity('required', false);
                    // } else {
                    // ctrl.$setValidity('required', true);
                    // }

                    setAsLoading(true);
                    setAsValid(false);

                    $http.get('/prism-cmti/2.1', {
                        params : {
                            requestType : requestTypeValue,
                            projectKey : viewValue.toUpperCase()
                        }
                    }).success(function(data) {
                        var isValid = data.isValid;
                        if (isValid) {
                            setAsLoading(false);
                            setAsValid(true);

                        } else {
                            setAsLoading(false);
                            setAsValid(false);
                        }
                    });

                    return viewValue;
                });

                function setAsLoading(bool) {
                    ctrl.$setValidity('loading', !bool);
                }

                function setAsValid(bool) {
                    ctrl.$setValidity('keyTaken', bool);
                }

            }
        };
    });

这是表单页面的 Controller :
angular.module('psm3App').controller(
        'ProjectCreateCtrl',
        [ '$scope', '$http', '$routeParams', '$location',
                function($scope, $http, $routeParams, $location) {
                    $scope.save = function() {
                            $http.post('/prism-cmti/2.1', {requestType:'vcs.stream.addProject', project:$scope.project})
                            .success(function(data) {
                                $location.path("/");
                            });
                        };
                }]);

在此错误之前,不知何故我也需要在我的自定义验证指令中处理所需的验证,如果我不这样做,所需的验证就会出错。现在想起来,也许这两个问题的根本原因是一样的:我的指令链接函数触发后,model值就没了。

我正在使用 Angular1.3 Beta 18 BTW。

任何帮助表示赞赏。提前致谢。

更新:
按照@ClarkPan 的回答,我将代码更新为 return viewValuectrl.$parsers.unshift()立即,这使得 required验证现在运行良好,所以我不再需要下面的行了。
        // if (viewValue == undefined || viewValue == null
                    // || viewValue == "") {
                    // ctrl.$setValidity('required', false);
                    // } else {
                    // ctrl.$setValidity('required', true);
                    // }

但是{{project.key}}仍然没有得到更新。
然后我尝试在这里注释掉这两行:
                    setAsLoading(true);
                    setAsValid(false);

型号值 {{project.key}}得到更新。我知道如果任何验证失败,模型值将被清除,但我认为
                      function(data) {
                            var isValid = data.isValid;
                            if (isValid) {
                                setAsLoading(false);
                                setAsValid(true);
                            } else {
                                setAsLoading(false);
                                setAsValid(false);
                            }
                        }

$http.get(...).success()应该在 $digest 循环中执行,这意味着应该更新模型值。

怎么了?

最佳答案

发生这种情况是因为如果模型中设置了任何无效标志,angular 不会对范围和 $modelValue 应用任何更改。当您开始验证过程时,您将“keyTaken”有效性标志设置为 false。这告诉 angular 不将值应用于模型。当 ajax 响应到达并且您将 'keyTaken' 有效性标志设置为 true 时,$modelValue 已经设置为 undefined 并且属性 'key' 消失了。尝试在 ajax 请求期间将所有有效性标志设置为 true。您必须避免在 ajax 调用之前调用 setAsLoading(true) 和 setAsValid(false) 并将所有有效性标志设置为 true。只有在ajax响应设置有效性标志之后。

关于触发自定义验证指令后,AngularJS ng-model 值丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25318495/

相关文章:

javascript - ui-router 解析在第一次加载时显示先前的解析结果,有时在重新加载时根本不显示

javascript - 如何一起使用 2 个指令 - Angular 翻译和 Angular chop ?

angularjs - Angular和Ionic,HTTP Get在真实设备IOS中不起作用

AngularJS 指令未调用

javascript - Angular js : call parent controller method from directive

javascript - 如何在没有 ng-repeat 的情况下制作模板并使用 angular-drag-and-drop-lists 将数据传递到 $scope?

javascript - 为什么 $scope 和 'this' 关键字在 Controller 内可以互换使用?

javascript - $http 成功功能 block 中不可用的动态元素和范围变量

javascript - AngularJS 的时间范围 slider

javascript - 如何在 Protractor 中选中多个复选框