markstewie
markstewie

Reputation: 9587

Angular.js rewrite ngShow function to directive

I'm looking to change the functionality defined in the ng-show directive I have on the form fields to display issues with a form field.

For example:

<span class="help-inline" ng-show="showError(schoolSignup.last_name, 'required')">This field is required</span>

Where schoolSignup.last_name is the reference to the model controller for the field, and 'required' is the validation property I'm looking for.

Defined in a controller as

$scope.showError = function(ngModelController, error) {
   return ngModelController.$dirty && ngModelController.$error[error];
 };

I've been banging my head against a wall trying to work out how to move this to a directive so I don't have to re-define this in every controller. I was thinking of defining it like...

<span class="help-inline" show-error="required" field="schoolSignup.last_name">This field is required</span>

This is as far as I've got

    .directive('showError', function () {
    return {
        restrict: 'A',
        scope:{
            field: "="
        },
        link: function(scope, elem, attrs, ctrl)
        {
            var errorType = attrs.showError;

            scope.errors = scope.field.$error[errorType];

           // NOT WORKING YET
        }
    };
});

How can I do this??

Upvotes: 1

Views: 376

Answers (1)

Michelle Tilley
Michelle Tilley

Reputation: 159135

You're on the right track; however, the dot in formName.fieldName will give you trouble using the object[field] syntax. Instead, you could do this pretty nicely with the $parse service (docs):

app.directive("showError", function($parse) {
  return {
    link: function(scope, elem, attrs) {
      // Returns a function that, when called with a scope,
      // evaluates the expression in `attrs.field` (e.g.
      // "schoolSignup.last_name") on the scope.
      var getter = $parse(attrs.field);

      // Every time a digest cycle fires...
      scope.$watch(function() {
        // ...get the input field specified in the `field` attribute...
        var field = getter(scope);
        // ...and check to see if the error specified by the
        // `show-error` attribute is set.
        if (field.$dirty && field.$error[attrs.showError]) {
          elem.show();
        } else {
          elem.hide();
        }
      });
    }
  };
});

Here's a working example: http://jsfiddle.net/BinaryMuse/Lh7YY/

Upvotes: 2

Related Questions