如何将任意属性添加到角度指令以进行数据验证

时间:2014-11-22 21:07:31

标签: angularjs angularjs-directive

我正在尝试创建一个angular指令,它将成为我们应用程序中输入字段的自定义标记。基本上它将做的是创建标签,输入字段和各种引导类,以便对它们有一致的外观。

如果我可以将适合特定输入的各种数据验证器(例如必需和自定义验证器)添加为自定义标签的属性,然后将那些添加到输入字段中,那么我希望如此对此进行验证。

我已经找到了一种方法,似乎将属性放在输入字段上,并且调用自定义验证器并正确评估数据,但表单似乎从未认为数据无效。我认为我有一个范围问题,其中输入无效是在指令的范围而不是父范围设置但我不是100%肯定,即使它是问题,我不知道如何修复它

以下是我希望其中一个标签看起来像

的示例
<textinput ng-model="TestValue" name="TestValue" text="Label Text" config="GetConfigurationForm()" ngx-ip-address required></textinput>

我希望生成类似

的内容
<div class="row">
    <div class="form-group" ng-class="{ 'has-error': IsInvalid() }">
        <label for="{{name}}" class="control-label">{{text}}</label>
        <input id="{{name}}" type="text" class="form-control" ng-model="ngModel" name="{{name}}" ngx-ip-address required>
    </div>
</div>

请注意,ngx-ip-address和required已被移动到输入字段属性。

我的控制器如下所示(抱歉这么久)

var app = angular.module('test', []);

app.directive('ngxIpAddress', function()
{
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attributes, ngModel)
        {
            ngModel.$validators.ngxIpAddress = function(modelValue, viewValue)
            {
                // Value being blank is OK
                if (ngModel.$isEmpty(modelValue))
                    return true;

                // If the string starts with a character then
                // this is not valid
                if (isNaN(parseInt(viewValue[0])))
                    return false;

                var blocks = viewValue.split(".");
                if(blocks.length === 4)
                {
                    return blocks.every(function(block)
                    {
                        return parseInt(block, 10) >= 0 && parseInt(block, 10) <= 255;
                    });
                }

                return false;
            };
        }
    };
});

    app.directive('textinput', function ()
    {
        return {
            restrict: 'E',
            scope: {
                //@ reads the attribute value, = provides two-way binding, & works with functions
                ngModel: '=',
                name: '@',
                text: '@',
                config: '&'
            },
            controller: function($scope) {
                $scope.IsInvalid = function()
                {
                    var getConfigurationFunction = $scope.config();
                    if (!getConfigurationFunction || !getConfigurationFunction[$scope.name])
                        return false;

                    return getConfigurationFunction[$scope.name].$invalid;
                };
            },
            link: function(scope, element, attributes) {
                var inputElement = element.find("input");
                for (var attribute in attributes.$attr)
                {
                    if (attribute !== "ngModel"
                        && attribute !== "name"
                        && attribute !== "text"
                        && attribute !== "config")
                    {
                        inputElement.attr(attribute, attributes[attribute]);
                    }
                }
            },
            template: '<div class="row">' +
                '<div class="form-group" ng-class="{ \'has-error\': IsInvalid() }">' +
                '<label for="{{name}}" class="control-label">{{text}}</label>' +
                '<input id="{{name}}" type="text" class="form-control" ng-model="ngModel" name="{{name}}">' +
                '</div>' +
                '</div>'
        };
    });

    app.controller(
        "TestController",
        [
            "$scope",
            function TestController(_scope)
            {
                _scope.TestValue = "TestTest";
                _scope.GetConfigurationForm = function()
                {
                  return _scope.ConfigurationForm;
                };
            }
        ]
    );

如果我将属性放在实际模板中,那么一切都按预期工作,如果数据不是IP地址,控件将变为红色。当我通过移动那些不起作用的属性来添加属性时。

这是一个显示我到目前为止所获得的内容:http://plnkr.co/edit/EXkz4jmRif1KY0MdIpiR

这是一个plunkr,显示我希望最终结果看起来像我将标签添加到模板而不是标签:http://plnkr.co/edit/mUGPcl1EzlHUiMrwshCr

为了使这更加有趣,将来我实际上还需要从外部作用域传递一个值到数据验证指令,但我想先让它工作。

1 个答案:

答案 0 :(得分:1)

Here你可能会找到正确答案。

此问题的原因是:

  1. attr会将属性从ngxIpAddress转换为ngxipaddress,即从大写转换为小写,您可以从此link中找到此问题。要解决此问题,只需将ngx-ip-address作为函数attr的参数传递。

  2. 当在另一个指令中使用一个指令时,
  3. $compile(inputElement)(scope);需要添加到指令中。这是一个link