sneeky
sneeky

Reputation: 1508

Angular validation in form field directive doesn't work

the validation isn't working in my formRow directive. I put a ng-form with the field name in the directive, but the [[ field ]].$invalid for example will not triggered. Does anybody know why?

Directive:

<li class="form__row" ng-form="[[ field ]]">
<div class="label">
    <label ng-class="{ 'required' : required == 'true' }" for="frm-[[ field ]]">[[ label ]]</label>
</div>
<div class="field" ng-switch="required" ng-class="{ 'field--invalid' : [[ field ]].$touched && [[ field ]].$invalid, 'field--valid': [[ field ]].$touched && [[ field ]].$valid }">
    <input ng-switch-when="true" type="[[ type ]]" name="[[ field ]]" id="frm-[[ field ]]" ng-model="record[ field ]" required>
    <input ng-switch-default type="[[ type ]]" name="[[ field ]]" id="frm-[[ field ]]" ng-model="record[ field ]" >
</div>

Directive.js

.directive('formRow', function () {
return {
    restrict: 'EA',
    templateUrl: FW.Config.submap + 'angular/_directives/formRow.html',
    replace: true,
    scope: {
        record: '=',
        type: '@',
        field: '@',
        label: '@',
        required: '@'
    },
    link: function($scope, element, attr) {
        // Wordt gezet bij form submit
        $scope.$on('record:invalid', function() {
            $scope[$scope.field].$setTouched;
        });
    }
}
})

Call from template:

<form name="formData" ng-submit="submit($event)" class="form--wide frm-login" novalidate>
    <ul>
        <form-row record="inloggen" field="emailadres" label="E-mailadres" type="email" required="true"></form-row>
        <form-row record="inloggen" field="wachtwoord" label="Wachtwoord" type="password" required="true"></form-row>
    </ul>

By the way: I use square brackets as $interpolateProvider symbols, because of the use of twig also in my templates.

Upvotes: 1

Views: 760

Answers (1)

dfsq
dfsq

Reputation: 193311

I'm not sure this is very good idea to create such directive, but the main problem and what makes it pretty awkward is that you are using nested form directive ngForm with the same name as corresponding element. It adds up to the scope level.

You can make ngClass work properly with this expression (I warned this looks weird :) :

ng-class="{ 'field--invalid' : this[field][field].$touched && this[field][field].$invalid, 'field--valid': this[field][field].$touched && this[field][field].$valid }"

First of all note, that you don't use interpolation tags inside of expressions, so you don't need [[ ]] inside ngClass. Then in order to resolve dynamic object property by variable name you would use bracket notation, hence

this[field][field] 

Here you have:

  • this points to current scope object
  • this[field] points to the ngForm object which has the same name as defined in field for input element and parent ngForm
  • this[field][field] point to individual input element within form accessed by this[field].

Demo: http://plnkr.co/edit/zarnKqPnYw4BNQQKVy9t?p=info

Upvotes: 1

Related Questions