Search code examples
angularjsangular-directive

Directive to show error messages


I have validation set up, and am using ngMessages to show errors. However I want to create a wrapper directive around ngMessages that adds some HTML (to avoid a lot of code duplication).

So instead of having to write this on each input:

<div class="help-block validator">
    <div ng-messages="registerForm.email.$error" ng-if="registerForm.email.$touched">
        <p ng-message="required">This field is required.</p>
    </div>
</div>

I'd just write something like this:

<error-message messages='{"required": "This field is required."}' error="registerForm.email.$error" touched="registerForm.email.$touched"></error-message>

The issue with my directive is that error and touched come up as strings, they don't get evaluated as JS expressions. I've tried to $eval them, but that throws an error.

Here's my directive:

angular
    .module('myApp')
    .directive("errorMessage", function () {
        return {
            restrict: "E",
            replace: true,
            scope: {
                'messages': '=',
                'error': '=',
                'touched': '='
            },
            template: '<div class="help-block validator">' +
                '<div ng-messages="error" ng-if="touched">' +
                    '<div ng-repeat="(key, message) in messages">' +
                        '<p ng-message="key">{{message}}</p>' +
                    '</div>' +
                '</div>' +
            '</div>',
            link: function (scope, elem, attrs) {
                scope.error = attrs.error;
                scope.touched = attrs.touched;
                scope.messages = scope.$eval(attrs.messages); // this works
            }
        };
    });

Any idea how I should go about doing this?


Solution

  • Found the issue. Looks like attrs wasn't what I needed. The properties were already in the scope. The code I ended up with is:

    angular
        .module('myApp')
        .directive("errorMessage", function () {
            return {
                restrict: "E",
                replace: true,
                scope: {
                    'messages': '=',
                    'error': '=',
                    'touched': '='
                },
                template: '<div class="help-block validator">' +
                    '<div ng-messages="error" ng-if="touched">' +
                        '<div ng-repeat="(key, message) in messages">' +
                            '<p ng-message="{{key}}">{{message}}</p>' +
                        '</div>' +
                    '</div>' +
                '</div>',
                link: function (scope, elem, attrs) {
    
                }
            };
        });