1

我正在尝试连接一个适配器以启用 ASP.Net MVC 为客户端验证发出的标记以在 AngularJS 中工作,我遇到了一个有趣的障碍。如果我required通过指令编译函数动态添加属性:

var myApp = angular.module('myApp', []).directive('valRequired', function() {
    return {
        compile: function (element) {

            element.attr('required', 'required');

            return function() { /* other custom logic here */ }
        }
    };
});

select元素不会按要求进行验证。仅在动态添加属性( jsFiddle )时才出现问题。

澄清:我想@Html.TextBoxFor(...)按原样使用 MVC。对于基于 DataAnnotations 的模型,data-val-*它发出的属性包含有关要运行哪些验证以及错误消息应该是什么的信息。我不是在寻找连接错误消息的帮助,我只需要能够连接一个指令,告诉input,select等使用required验证。

4

2 回答 2

1

让我开始吧,这并不漂亮,但它确实有效。我尝试了不同的方法来使本机指令起作用,但无济于事。看起来当该指令执行时为时已晚。

这将查找您的 data-val-required 属性并向元素添加验证。

它将触发所有相同的事情,因此myForm.mySelect.$valid仍然可以正常工作myForm.mySelect.$error.required

http://jsfiddle.net/TheSharpieOne/knc8p/

var myApp = angular.module('myApp', []).directive('valRequired', function () {
    return {
        require: 'ngModel',
        restrict: 'A',
        link: function (scope, elm, attr, ctrl) {
            if (!ctrl || !attr.valRequired) return;
            attr.required = true; // force truthy in case we are on non input element

            var validator = function (value) {
                if (attr.required && (value == '' || value === false)) {
                    ctrl.$setValidity('required', false);
                    return;
                } else {
                    ctrl.$setValidity('required', true);
                    return value;
                }
            };

            ctrl.$formatters.push(validator);
            ctrl.$parsers.unshift(validator);

            attr.$observe('required', function () {
                validator(ctrl.$viewValue);
            });
        }
    };
});


function MyCtrl($scope, $http) {
    $scope.model = {
        property: ''
    };
}
于 2013-09-10T17:33:32.490 回答
0

更新 我想到了一个更好的方法来回答这个问题。旧答案低于新答案。


您可以获得对 AngularJS 的 required 指令的引用并将其应用于您自己的指令。继承人将执行此操作的代码示例:

var myApp = angular.module('myApp', []).directive('valRequired', function(requiredDirective) {
    var newDirective = {},
        angularDirective = requiredDirective[0]; //This assumes angular's required directive is the first one

    //Copy over all other properties of the angular directive
    angular.extend(newDirective, angularDirective);

    //Change the name of our directive back to valRequired
    newDirective.name = 'valRequired';

    //Provide our own logic in the linking function
    newDirective.link = function(scope, element, attr, ctrl){
        //Super call
        angularDirective.link.apply(this, arguments);
        if(attr.valRequired === 'required'){
            attr.$set('ngRequired', 'true');
        } else {
            attr.$set('ngRequired', 'false');
        }
    }

    return newDirective;
});

<input data-val-required="required" ng-model="foo" />

旧答案

使用 jQuery 或 jQLite 的attr()方法不会改变AngularJs 的 Attributes object。Attributes 对象是指令用作其逻辑值的对象。

您还需要包含 ng-required 属性,尽管您不需要将任何角度表达式绑定到它。这个问题将帮助你: Html5 data-* with asp.net mvc TextboxFor html attributes

这样做的原因是我们需要强制 Angular 将指令应用于该节点。在模板的编译阶段之后更新属性不会通知 Angular 将新指令应用于节点。

这应该有效:

var myApp = angular.module('myApp', []).directive('valRequired', function() {
    return {
        priority : 101, //The priority needs to run higher than 100 to get around angularjs' default priority for ngRequired
        link: function (scope, element, attr) {

            if(attr.valRequired === 'true'){
                attr.$set('ngRequired', 'true');
            } else {
                attr.$set('ngRequired', 'false');
            }
        }
    };
});

<input ng-required data-val-required="true" ng-model="foo" />
于 2013-09-12T05:33:46.697 回答