teepusink
teepusink

Reputation: 28892

AngularJS - Directive scope issue with form validation

I'm working on a form input directive.
http://jsfiddle.net/TR9Qt/1/

<form name="form">
<ng-form-field label="Email validation NOT working"></ng-form-field>
<label for="test_email">Test Email with working validation</label>
<input type="email" name="test_email"
ng-model="formData.testEmail" placeholder="Email" required />
<div class="error-message" ng-show="form.test_email.$dirty && form.test_email.$invalid"> <span ng-show="form.test_email.$error.required">Tell us your email.</span>

    <span
    ng-show="form.test_email.$error.email">This is not a valid email.</span>
</div>

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

myApp.directive('ngFormField', function ($compile) {
var labelTemplate = '<label for="user_email">{{label}}</label>';
var inputTemplate = '<input type="email" name="user_email" ng-model="formData.email" placeholder="Email" required />' +

    '<div class="error-message" ng-show="form.user_email.$dirty && form.user_email.$invalid">' +
    '<span ng-show="form.user_email.$error.required">Tell us your email.</span>' +
    '<span ng-show="form.user_email.$error.email">This is not a valid email.</span>' +
    '</div>';


return {
    transclude: true,
    scope: {
        label: '@'
    },
    // append
    replace: true,
    // attribute restriction
    restrict: 'E',
    controller: function ($scope, $element, $attrs) {},
    // linking method
    link: function ($scope, element, attrs) {
        element.html(labelTemplate + inputTemplate);

        $compile(element.contents())($scope);
    }
}

});

Why wouldn't the form validate when I put it in the directive?

Thanks,
Tee

Upvotes: 3

Views: 2328

Answers (2)

mortalapeman
mortalapeman

Reputation: 1425

A little late to the party, but the problem you were running into was that you were using an isolated scope when you were trying to compile. The isolated scope doesn't inherit from the parent directly, but it is still available via $parent. I solved your issue by just attaching the label attribute value to the current scope; this may not be what you want, but it solves your immediate problem.

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

myApp.directive('ngFormField', function ($compile) {
    var labelTemplate = '{{label}}';
    var inputTemplate = '' +

        '' +
        'Tell us your email.' +
        'This is not a valid email.' +
        '';
    return {
        // append
        replace: true,
        // attribute restriction
        restrict: 'E',
        // linking method
        link: function ($scope, element, attrs) {
            $scope.label = attrs.label;
            element.html(labelTemplate + inputTemplate);
            $compile(element.contents())($scope);
        }
    };
});

Working plunker

Upvotes: 1

Sharondio
Sharondio

Reputation: 2614

I'm not a directives pro yet, but two things jumped out at me:

  1. You don't really need to compile your directive unless it's being used in an ng-repeat.
  2. Your directive was tied to the label instead of the form field.

    <input 
        ng-form-field
        type="email" 
        name="test_email"
        ng-model="formData.testEmail" 
        placeholder="Email" 
        required />
    

http://jsfiddle.net/sharondio/c8hwj/

Upvotes: 1

Related Questions