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

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

问题描述

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

ng-model="project.key"

并且经过验证,project.key 不再存在于范围中.我想不知何故我理解 AngularJS 是错误的并且做错了.

代码会说话.

这是我的 html 页面:

 

...<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="url 中使用的唯一键"my-uniquekey="vcs.stream.isProjectKeyValid" 需要/><div ng-messages="form.key.$error" ng-if="form.key.$dirty"类=帮助块"><div ng-message="required">需要项目密钥.</div><div ng-message="loading">检查密钥是否有效...</div><div ng-message="keyTaken">项目密钥已被使用,请使用另一个.

<div class="col-sm-offset-5 col-sm-10"><br><a href="#/" class="btn">取消</a><button ng-click="save()" ng-disabled="form.$invalid"class="btn btn-primary">保存</button><button ng-click="destroy()" ng-show="project.$key"class="btn btn-danger">删除</button>

</表单>

这是我的指令:

 .directive('myUniquekey', function($http) {返回 {限制:'A',要求:'ngModel',链接:功能(范围,元素,属性,ctrl){var requestTypeValue = attrs.myUniquekey;ctrl.$parsers.unshift(function(viewValue) {//if (viewValue == undefined || viewValue == null//||视图值 == "") {//ctrl.$setValidity('required', false);//} 别的 {//ctrl.$setValidity('required', true);//}setAsLoading(true);setAsValid(false);$http.get('/prism-cmti/2.1', {参数:{请求类型:请求类型值,projectKey : viewValue.toUpperCase()}}).成功(功能(数据){var isValid = data.isValid;如果(有效){setAsLoading(false);setAsValid(true);} 别的 {setAsLoading(false);setAsValid(false);}});返回视图值;});函数 setAsLoading(bool) {ctrl.$setValidity('loading', !bool);}函数 setAsValid(bool) {ctrl.$setValidity('keyTaken', bool);}}};});

这是表单页面的控制器:

angular.module('psm3App').controller('项目创建控件',[ '$scope', '$http', '$routeParams', '$location',功能($scope,$http,$routeParams,$location){$scope.save = function() {$http.post('/prism-cmti/2.1', {requestType:'vcs.stream.addProject', project:$scope.project}).成功(功能(数据){$location.path("/");});};}]);

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

顺便说一句,我使用的是 Angular1.3 Beta 18.

感谢任何帮助.提前致谢.

更新:按照@ClarkPan 的回答,我立即将我的代码更新为 ctrl.$parsers.unshift() 中的 return viewValue,这使得 required 验证效果很好现在,我不再需要下面的行了.

//if (viewValue == undefined || viewValue == null//||视图值 == "") {//ctrl.$setValidity('required', false);//} 别的 {//ctrl.$setValidity('required', true);//}

但是 {{project.key}} 仍然没有更新.然后我试着在这里注释掉这两行:

 setAsLoading(true);setAsValid(false);

模型值 {{project.key}} 已更新.我知道如果任何验证失败,模型值将被清除,但我认为

 函数(数据){var isValid = data.isValid;如果(有效){setAsLoading(false);setAsValid(true);} 别的 {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响应设置了有效性标志之后.

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" 

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

Code speaks.

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>

And here's my directive:

    .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.

I'm using Angular1.3 Beta 18 BTW.

Any help is appreciated. Thanks in advance.

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

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

                    setAsLoading(true);
                    setAsValid(false);

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

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

What is wrong?

解决方案

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-model 值丢失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆