5
votes

Being rather new to Angularjs, I am creating textbox-label combinations in Angularjs using directives. It's working very well, but I can't get validation to work. Here is a stripped-down example.

The Html:

<form name="form" novalidate ng-app="myapp">
<input type="text" name="myfield" ng-model="myfield" required />{{myfield}}
<span ng-show="form.myfield.$error.required">ERROR MSG WORKING</span> 
<br>
<div mydirective FIELD="myfield2" />
</form>

The Javascript:

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

myapp.directive('mydirective', function () {
    return {
        restrict: 'A',
        scope: { ngModel: '=' },
        template: '<input type="text" name="FIELD" ng-model="FIELD" />{{FIELD}}
        <span ng-show="form.FIELD.$error.required">ERROR MSG NOT WORKING</span>'
    };
});

The hard coded input - myfield - works, the other - myfield2 - doesn't (the binding does, just not the required-error message).

How do I tell the ng-show attribute to sort of "replace" FIELD in form.FIELD.$error.required by myfield2?

Here is a jsFiddle.

1
In the jsFiddle, the input defined in the directive does not include the "required" attribute. That's not what is causing the problem, but will be needed to get the behaviour you want. - George Thomas
@GeorgeThomas: Thanks, I'll fix this. - Olaf

1 Answers

14
votes

The problem is that your directive creates a new scope for the directive, this new scope does not have access to the form object in the parent scope.

I came up with two solutions, though I suspect there is a more elegant "Angular" way to do this:

Passing down the form object

Your view becomes:

<div mydirective FIELD="myfield2" form="form" />

And the scope definition object:

return {
    restrict: 'A',
    scope: {
        ngModel: '=',
        form: '='
    },
    template: '<input type="text" name="FIELD" ng-model="FIELD" required/>{{FIELD}}<span ng-show="form.FIELD.$error.required">ERROR MSG NOT WORKING</span>'
};

I've updated the fiddle with this code: http://jsfiddle.net/pTapw/4/

Using a controller

return {
    restrict: 'A',
    controller: function($scope){
        $scope.form = $scope.$parent.form;   
    },
    scope: {
        ngModel: '='
    },
    template: '<input type="text" name="FIELD" ng-model="FIELD" required/>{{FIELD}}<span ng-show="form.FIELD.$error.required">ERROR MSG NOT WORKING</span>'
};