AngularJS NG-模型值自定义的验证指令被触发后会丢失 [英] AngularJS ng-model value is lost after custom validation directive is triggered

查看:117
本文介绍了AngularJS NG-模型值自定义的验证指令被触发后会丢失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个自定义的验证指令,并在一个形式使用它。它可以毫无问题地触发,但是验证触发后,我发现,模型值只是丢失。说我有

I created a custom validation directive and used it in a form. It can be triggered with no problem, but after the validation is triggered, I found that the model value is just lost. Say I have

ng-model="project.key" 

和验证后, project.key 不在范围存在了。我想,不知何故,我知道错了AngularJS和做错了什么。

and after validation, project.key doesn't exist in the scope anymore. I think somehow I understood AngularJS wrong and did something wrong.

code说。

下面是我的html页面:

Here is my html page:

 <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);
                }

            }
        };
    });

下面是表单页面控制器:

Here's the controller for the form page:

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("/");
                            });
                        };
                }]);

这个错误之前,不知何故,我需要处理在我的自定义验证指令所要求的验证过,如果我不这样做,需要验证会出问题。现在我想起来了,也许这两个问题的根本原因是一样的:我的指令链接功能被触发后,该模型的价值消失了。

Before this bug, somehow I need to handle the required validation in my custom validation directive too, if I don't do it, required validation would go wrong. Now I think of it, maybe the root cause of these two problems is the same: the model value is gone after my directive link function is triggered.

我使用Angular1.3测试18 BTW。

I'm using Angular1.3 Beta 18 BTW.

任何帮助是AP preciated。提前致谢。

Any help is appreciated. Thanks in advance.

更新:
其次@ ClarkPan的回答,我更新了我的code到控制$ parsers.unshift返回viewValue ()随即,这使得要求验证效果很好了,所以我不需要任何以下多行。

Update: Followed @ClarkPan's answer, I updated my code to return viewValue in ctrl.$parsers.unshift() immediately, which makes required validation works well now, so I don't need lines below any more.

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

{{} project.key} 仍然没有得到更新。
然后我试图在这里注释掉以下两行:

But the {{project.key}} still didn't get updated. Then I tried to comment out these two lines here:

                    setAsLoading(true);
                    setAsValid(false);

示范值 {{} project.key} 得到更新。我知道,如果任何验证失败,该模型的价值将被清零,但我认为

Model value {{project.key}} got updated. I know that if any validation fails, the model value will be cleared, but I thought

                      function(data) {
                            var isValid = data.isValid;
                            if (isValid) {
                                setAsLoading(false);
                                setAsValid(true);
                            } else {
                                setAsLoading(false);
                                setAsValid(false);
                            }
                        }

$ http.get(...)。成功()应$消化周期,这意味着模型值应更新被执行。

in $http.get(...).success() should be executed in $digest cycle, which means the model value should be updated.

什么是错的?

推荐答案

这是发生,因为如果有任何无效标志在模型中设置角度不适的任何变化的范围和$ modelValue。当您启动验证过程中,您在keyTaken有效性标志设置为false。这是在告诉为角度值不适用于模型。当Ajax响应到达你的keyTaken有效性标志设置为true,则$ modelValue已经被设置为未定义和财产'键'不见了。尽量保持设置为true的有效性标识Ajax请求中。 Ajax调用之前,必须避免setAsLoading(真)和setAsValid(假)的调用,并保持设置为true,所有的有效性标志。只有在Ajax响应设置有效性标志。

This is happening because angular does not apply any change to the scope and $modelValue if there is any invalid flag set in the model. When you start the validation process, you are setting the 'keyTaken' validity flag to false. That is telling to angular not apply the value to the model. When the ajax response arrives and you set the 'keyTaken' validity flag to true, the $modelValue was already set to undefined and the property 'key' was gone. Try to keep all validity flags set to true during the ajax request. You must avoid the calls to setAsLoading(true) and setAsValid(false) before the ajax call and keep all validity flags set to true. Only after the ajax response set the validity flag.

这篇关于AngularJS NG-模型值自定义的验证指令被触发后会丢失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆