Как создать угловую директиву ввода, которая работает с проверкой формы

Как создать угловую директиву, которая добавляет вход в форму, но также работает с проверкой формы.

Например, следующая директива создает текстовый ввод:

    var template = '\
<div class="control-group" ng-class="{ \'error\': {{formName}}[\'{{fieldName}}\'].$invalid}">\
    <label for="{{formName}}-{{fieldName}} class="control-label">{{label}}</label>\
    <div class="controls">\
        <input id="{{formName}}-{{fieldName}}" name="{{fieldName}}" type="text" ng-model="model" />\
    </div>\
</div>\
';

angular

    .module('common')

    .directive('formTextField', ['$compile', function ($compile) {
        return {
            replace: true,
            restrict: 'E',
            scope: {
                model: '=iwModel',
                formName: '@iwFormName',
                fieldName: '@iwFieldName',
                label: '@iwLabel'
            },
            transclude: false,
            template: template
        };
    }])

;

Однако входные данные не добавляются в переменную формы ($scope.formName). Я смог обойти это, используя директиву dynamicName из следующего вопроса Angularjs о стеке потока: проверка формы и директива input, но ng-class все равно не будет работать.


Обновить

Теперь кажется, что работает, но это похоже на взломать. Я думал, что мне нужна область, чтобы получить имена форм и полей, однако я могу прочитать это непосредственно из атрибутов. При этом показано поле в переменной формы области контроллера. Однако атрибут ng-class не применяется. Единственный способ обойти это - добавить элемент html во второй раз, когда область станет доступна.

jsFiddle здесь

    var template = '\
<div class="control-group">\
    <label class="control-label"></label>\
    <div class="controls">\
        <input class="input-xlarge" type="text" />\
    </div>\
</div>\
';

angular

    .module('common')

    .directive('formTextField', ['$compile', function ($compile) {
        return {
            replace: true,
            restrict: 'E',
            scope: false,
            compile: function compile(tElement, tAttrs, transclude) {
                var elem = $(template);
                var formName = tAttrs.iwFormName;
                var fieldName = tAttrs.iwFieldName;
                var label = tAttrs.iwLabel;
                var model = tAttrs.iwModel;
                elem.attr('ng-class', '{ \'error\': ' + formName + '[\'' + fieldName + '\'].$invalid }');
                elem.find('label').attr('for', formName + '-' + fieldName);
                elem.find('label').html(label);
                elem.find('input').attr('id', formName + '-' + fieldName);
                elem.find('input').attr('name', fieldName);
                elem.find('input').attr('ng-model', model);

                // This one is required so that angular adds the input to the controllers form scope variable
                tElement.replaceWith(elem);

                return {
                    pre: function preLink(scope, iElement, iAttrs, controller) {
                        // This one is required for ng-class to apply correctly
                        elem.replaceWith($compile(elem)(scope));
                    }
                };

            }
        };
    }])

;

1 ответ

Когда я делаю что-то подобное, я использую директиву compile Функция для создания моего HTML до его обработки. Например:

myApp.directive('specialInput', ['$compile', function($compile){
    return {
        // create child scope for control
        scope: true,
        compile: function(elem, attrs) {
            // use this area to build your desired dom object tree using angular.element (eg:)
            var input = angular.element('<input/>');

            // Once you have built and setup your html, replace the provided directive element
            elem.replaceWith(input);

            // Also note, that if you need the regular link function, 
            // you can return one from here like so (although optional)
            return function(scope, elem, attrs) {
                // do link function stuff here
            };
        }
    };
}]);
Другие вопросы по тегам