MarekLi
MarekLi

Reputation: 951

How to validate dynamic form fields in angular directive?

I would like to create form with fields created in directive. Data binding of data working correctly but validation doesn't work.

this is html:

<body ng-controller="MainCtrl">
  <h1>form</h1>
  <form name="form">
      <div ng-repeat="conf in config">
          <div field data="data" conf="conf"></div>
      </div>
  </form>
  <pre>{{data|json}}</pre>
</body>

controller and field directive:

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

app.controller('MainCtrl', function($scope) {
    $scope.data = {name: '', age: ''}
    $scope.config = [
        {field: 'name', required:true},
        {field: 'age'}
    ];
});

app.directive('field', function ($compile) {
    return {
        scope: {
            data: '=',
            conf: '='
        },
        link: function linkFn(scope, element, attrs) {
            // field container
            var row = angular.element('<div></div>');

            // label
            row.append(scope.conf.field + ': ');

            // field input
            var field = angular.element('<input type="text" />');
            field.attr('name', scope.conf.field);
            field.attr('ng-model', 'data.' + scope.conf.field);
            if (scope.conf.required) {
                field.attr('required', 'required');
            }
            row.append(field);

            // validation
            if (scope.conf.required) {
                var required = angular.element('<span>required</span>');
                required.attr('ng-show', 
                    'form.' + scope.conf.field + '.$error.required');
                row.append(required);
            }

            $compile(row)(scope);
            element.append(row);
        }
    }
});

problem is that validation for field name doesn't work and validation text required is never shown. May be form in ng-show is unknown in directive. But I don't know how to pass form into field directive. Can you help me how to fix it? Thanks.

here is live code: http://plnkr.co/edit/j0xc7iV1Sqid2VK6rMDF?p=preview

Upvotes: 8

Views: 6392

Answers (3)

nelsonomuto
nelsonomuto

Reputation: 63

Here is a plunker forked from yours to fix you're issue: http://plnkr.co/edit/qoMOPRoSnyIdMiZnbnDF?p=preview

To summarize, I added a watch that will toggle the error message instead of using the ng-show directive. Things can get hairy when you attempt to dynamically add a directive within a directive link. For a simple use case as this, it is quicker to add your own watch.

You may also look at this directive which is preconfigured to handle many use cases for validation as well as allow you to create custom validations easily https://github.com/nelsonomuto/angular-ui-form-validation

var toggleRequiredErrorMessage = function (invalid) {
    if(invalid === true) {
        addRequiredErrorMessage();
    } else {
        removeRequiredErrorMessage();
    }
};
scope.$watch( watchIfRequired, toggleRequiredErrorMessage );

Upvotes: 0

Vladimir
Vladimir

Reputation: 205

Todo:

before:

$compile(row)(scope);
element.append(row);

after:

element.append(row);
$compile(row)(scope);

p/s in 'planker' for facilities add css:

.ng-invalid {
  border: 1px solid red;
}

Upvotes: 5

Ygor Cardoso
Ygor Cardoso

Reputation: 261

You'll need to use ng-form directive and push the dynamic field directly into form object.

This thread can help you out: https://github.com/angular/angular.js/issues/1404

Upvotes: 2

Related Questions