5

I have the following Angular/HTML which uses Bootstrap CSS classes to indicate whether a form is valid or not using Angular validation.

<form name="editor" novalidate>
    <div class="form-group" ng-class="{'has-error': editor.name.$dirty && (editor.name.$error.invalid || editor.name.$error.required)}"> 
         <input type="text" class="form-control" name="name" maxlength="150" data-ng-model="name" required />
    </div>
</form>

With more than one div.form-group obviously there is a lot of code repetition. What I would like to do is create an Angular attribute directive which will update the class of the div.form-group element if the input contained within it is invalid.

This is the markup I would like to get to:

<div class="form-group" data-form-group data-input="editor.name">
     ...
</div>

I have the following shell of a directive but I don't know how to monitor the editor.name (or input attribute) in order to update the class.

myApp.directive("formGroup", function () {
return {
    restrict: "A",
    scope: {
        input: "@"
    },
    replace: false,
    link: function (scope, elem, attrs) {

    }
    };
});

I assume I need to put the relevant code in the link function, and perhaps using $watch but other than that I am a bit in the dark

3
  • You are actually spot on. If i were you, i would start a plunker, and try to code it yourself. If you are stuck, come back here, and link the plunker. I do think that your directive scope needs to be '=' instead of @, and that you will not need a $watch, because the value you would watch will be already bound in your view template (in the form of hte input field ). But try it out yourself, its the best way to learn Commented Feb 2, 2016 at 12:20
  • Err - tried that! Hence why I'm posting here. Commented Feb 2, 2016 at 12:26
  • can u then please link the plunker? Commented Feb 2, 2016 at 12:26

2 Answers 2

1

you should use ngModelController properties for doing this:

myApp.directive("formGroupElement", function () {
    return {
       restrict: "A",
       require: "ngModel"
       scope: {
            input: "@"
       },
       replace: false,
       link: function (scope, elem, attrs, ngModelController) {
          //ngModelController.$setValidity();
       }
   };
});

or ngFormController:

myApp.directive("formGroup", function () {
    return {
       restrict: "A",
       require: "ngForm"
       scope: {
            input: "@"
       },
       replace: false,
       link: function (scope, elem, attrs, ngFormController) {
          //ngFormController.$setValidity();
       }
   };
});
Sign up to request clarification or add additional context in comments.

1 Comment

I might have misunderstood your answer, but I don't want to actually set the validity in the directive. All I want to do is update the CSS class of a div based on validation that has already been done. I suppose what I really need the answer to is how to get hold of the editor.name.$error object inside the directive link function?
1

I have ended up with the following:

myApp.directive("formGroup", function ($parse) {
  return {
    restrict: "A",
    scope: {
        input: "@"
    },
    replace: false,
    require: "^form",
    link: function (scope, elem, attrs, ctrl) {

        var expression = [ctrl.$name, scope.input, "$invalid"].join(".");

        scope.$parent.$watch(expression, function (val) {
            alert(expression + " " + val); // Pops the value.
        });
    }
  };
});

Note that although the expression in the HTML is editor.name.$error.invalid, in the link function it is editor.name.$invalid.

Using the form controller means I don't have to set the ng-model attribute on the <div>.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.