Angularjs: проверка формы в поле ввода, сгенерированная директивой

Я создал директиву, которая генерирует поле ввода на основе метаданных ($scope.meta). Моя проблема заключается в поддержке проверки формы angular.

Plunkr: http://plnkr.co/edit/AfR5cWyywGlCECS6h6Dr?p=preview

Объяснение: директива принимает параметр meta, который описывает тип входного поля и другую связанную информацию для отображения поля. Все атрибуты, определенные в директиве, будут скопированы в элемент и, наконец, заменят директиву после компиляции и компоновки.

Вид:

<form name="userForm">
    <!-- Username -->
    <poly-field ng-model="storage" meta="meta" key="username" name="username" ng-minlength="3" ng-maxlength="8"></poly-field>
    <p ng-show="userForm.username.$error.minlength" class="help-block">Username is too short.</p>
    <p ng-show="userForm.username.$error.maxlength" class="help-block">Username too long</p>

    <!-- Email -->
    <poly-field ng-model="storage" meta="meta" key="email" name="email" ng-required></poly-field>
    <p ng-show="userForm.email.$error.minlength" class="help-block">Email is too short.</p>
    <p ng-show="userForm.email.$error.maxlength" class="help-block">Email is too long</p>
</form>

Ввод имени пользователя длиннее или короче разрешенного должен показать мне ошибку. Пропуск поля электронной почты также показывает мне ошибку.

Вот исходный код View после применения директивы:

<form name="userForm" class="ng-pristine ng-valid ng-valid-required">
        <!-- Username -->
        <input type="undefined" ng-model="storage.username" meta="meta" key="username" name="username" ng-minlength="3" ng-maxlength="8" class="ng-scope ng-valid-minlength ng-dirty ng-valid ng-valid-maxlength">
        <p ng-show="userForm.username.$error.minlength" class="help-block ng-hide">Username is too short.</p>
        <p ng-show="userForm.username.$error.maxlength" class="help-block ng-hide">Username too long</p>

        <!-- Email -->
        <input type="undefined" ng-model="storage.email" meta="meta" key="email" name="email" ng-required="" class="ng-scope ng-valid ng-valid-required ng-dirty">
        <p ng-show="userForm.email.$error.minlength" class="help-block ng-hide">Email is too short.</p>
        <p ng-show="userForm.email.$error.maxlength" class="help-block ng-hide">Email is too long</p>
</form>

Вот модель, с которой работает представление и директива, она объявлена ​​в ParentCtrl.

$scope.storage = {
    username: "Kitkat",
    email: "[email protected]"
};

Это метаинформация, которая говорит о том, как выглядит поле ввода (это текст? дата? и т. д.)

 $scope.meta = {
    username: { type: "text" },
    email: { type: "text" }
};

Декларация директивы:

app.directive('polyField', function($compile) {
    var linkFn = function(scope, element, attributes) {
        // create input element depending on the type
        var template = document.createElement("input");
        template.type = scope.storage[attributes.key].type;

        // copy all attributes
        for (var attr in attributes.$attr) {
            if (attributes.$attr[attr] == 'ng-model') {
                template.setAttribute('ng-model', attributes[attr] + '.' + attributes.key);
            } else {
                template.setAttribute(attributes.$attr[attr], attributes[attr]);
            }
        }

        // template compilation, linking and element replacement
        template = angular.element(template.outerHTML);
        var linkTemplate = $compile(template);
        var domElement = linkTemplate(scope);
        element.replaceWith(domElement);
    }

    var directive = {
        restrict: 'E',
        scope: { 
            meta: '=',
            storage: '=ngModel',
            key: '=',
        },
        link: linkFn
    };

    return directive;
  });

Некоторые мысли:
Каждая директива создает изолированную область, поэтому внутри директивы userForm невидима, однако двусторонняя привязка storage (ng-модель) видна из области директивы и родительской области, если userForm видит, что внутри storage должно быть все в порядке, не так ли?

Я попытался передать userForm в область действия директивы:

// directive
scope: {
        meta: '=',
        storage: '=ngModel',
        key: '=',
        userForm: '='
}

// template
<poly-field user-form="userForm" ng-model="storage" meta="meta" key="username" name="username" ng-minlength="3" ng-maxlength="8"></poly-field>

но без эффекта.

Когда я смотрю в область директив, в поле userForm я вижу, что поле ввода на самом деле $dirty: false, $invalid: true, и что после того, как я ввел имя пользователя/адрес электронной почты,

В исходном коде кажется, что классы проверки применяются правильно: ng-valid-minlength ng-dirty ng-invalid ng-invalid-maxlength по-прежнему, ошибки проверки не отображаются.

Могу ли я что-нибудь с этим сделать?


person psycat    schedule 18.08.2014    source источник


Ответы (1)


Для того, чтобы проверка формы Angular могла сработать, ngModel ищет родительскую директиву ngForm/form на этапе создания экземпляра своего контроллера (до этапа предварительной компоновки).

Поскольку вы компилируете и связываете элемент перед добавлением его в DOM, в это время нет родительского элемента, поэтому он не может быть зарегистрирован.

Вам просто нужно сначала вставить элемент в DOM, а затем скомпилировать и связать его.

Обновлен plunkr

person gkalpak    schedule 18.08.2014