10

Rewriting this question for clarification

How can I check transcluded form's validity in directive ? I would like to check myForm.$valid in link function of directive. I will inject different sort of forms into my directive or use my directive in different forms you can say

Difficulty is that scope is isolated and non of following answer worked for me.

Please find complete code here,

https://plnkr.co/edit/K3IrE5KVehWXFM9JEMvE?p=preview

I want to disable "Save" button when form is not valid.

Mathematics
  • 7,314
  • 25
  • 77
  • 152
  • 1
    You could try starting with valid HTML. Spans can't contain divs or forms. – Quentin Aug 09 '16 at 13:40
  • In this case html standarts doesn't make any difference. Anyway, can you provide a working fiddle? – lenilsondc Aug 09 '16 at 13:43
  • Have a look at following tutorial http://code.realcrowd.com/on-the-bleeding-edge-advanced-angularjs-form-validation/ – daan.desmedt Aug 09 '16 at 13:44
  • Myaybe you should watch http://stackoverflow.com/questions/28677638/angularjs-1-3-ng-change-like-functionality-for-the-entire-form (possible duplicate) – Dan M. CISSOKHO Aug 09 '16 at 13:44
  • I created a plunk from your code and it seems to be working fine. Just remember, it will generate a log only when validity state of your form changes from valid to invalid or vice versa. – Dev Shah Aug 09 '16 at 13:50
  • https://plnkr.co/edit/lW3e4p – Dev Shah Aug 09 '16 at 14:04
  • @DevShah's example works because `myForm.$valid` actually changes, but yours doesn't have any directive that affects this state so I guess that is the reason because your `$watch` never triggers. – lenilsondc Aug 09 '16 at 14:11

4 Answers4

8

To answer your primary question, you can expose and bind the form like any other model value:

angular.module("main", [])
  .directive("formDirective", formDirective);

function formDirective() {
  return {
    restrict: "A",
    scope: {
      formModel: "=formModel"
    },
    link: function (scope, element, attrs) {
      scope.$watch("formModel.$valid", function (newValue, oldValue) {
       console.log(newValue, oldValue);
      });
    }
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="main">
 <div form-directive form-model="myForm">
    <div>
    <form name="myForm">
       <div>
        <input type="text" ng-model="name" required="required">
       </div>
         Valid: {{myForm.$valid}}
    </form>
    <div>
 </div>
</div>

However, as became clear from our conversation on chat, your overall problem is more complicated.

I have added a working example here: https://plnkr.co/edit/lkfdmc0PLRadfYFVhFAm?p=preview

The key aspects to realize here are:

  • You're opening a modal dialog with $uibModal.open, which will instantiate the referenced controller editCtrl and load your template editCtrl.html.
  • The loading process includes that Angular is compiling the template. This template includes a directive at the root level, so that directive needs to be compiled as well.
  • That directive uses transclusion and loads the template dialog.html. It is important to note here, that the scope of your esDlg directive is now available in the template of dialog.html, so you can access all properties defined in the scope of the directive declaration.
    You've already been making use of this with the dialog title and text.
  • All we need to do is to bind the validity information here as well, so that we can use it in the dialog.
Oliver Salzburg
  • 21,652
  • 20
  • 93
  • 138
3

angular.module("main", [])
  .directive("formDirective", formDirective);

function formDirective() {
  return {
    restrict: "A",
    scope: {
      formModel: "=name"
    },
    link: function (scope, element, attrs) {
      scope.$watch("formModel.$valid", function (newValue, oldValue) {
       console.log(newValue, oldValue);
      });
    }
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="main">
 <div my-directive>
    <div>
    <form name="myForm" form-directive>
       <div>
        <input type="text" ng-model="name" required="required">
       </div>
         Valid: {{myForm.$valid}}
    </form>
    <div>
 </div>
</div>

I advise you to use angular-auto-validate

Rafael Teles
  • 2,708
  • 2
  • 16
  • 32
  • where myForm is coming from in scope.$watch function ? :S – Mathematics Aug 09 '16 at 13:48
  • Sorry I first misunderstood your question. Just rewrote the answer – Rafael Teles Aug 09 '16 at 14:09
  • Hi, I have a isolated scope, please check the plunker I added, sorry I should had mentioned it before but I am new to angular so didn't understood it well – Mathematics Aug 10 '16 at 08:32
  • @Mathematics do you want to use the "dlgNegClick" function in your dialog template? I'm not understanding your question. What do you want to use to check if the form is valid? The above code works just fine... you can get the name of the form dynamically with the attrs variable, check the edited snippet – Rafael Teles Aug 10 '16 at 12:52
  • please look at scope, your scope is not declared, mine is isolated – Mathematics Aug 10 '16 at 14:49
  • Sorry @Mathematics my bad, please check the edited snippet, is that what you are looking for? – Rafael Teles Aug 10 '16 at 18:47
  • Thanks, it works but does this means I need to create a scope variable for each form control ? :S... if yes then it will be very difficult for me as I have several forms with several fields :( – Mathematics Aug 23 '16 at 09:11
2

Are you defining the directive properly? Check out this plunker where validity's logged as you would expect.

function MyDirective() {
  return {
    restrict: 'AE',
    scope: true,
    link: function (scope, element, attrs) {
      scope.$watch('myForm.$valid', function (validity) {
        console.log(validity);
      });
    }
  }
}
chris
  • 1,787
  • 1
  • 13
  • 13
  • Hi, I have a isolated scope, please check the plunker I added, sorry I should had mentioned it before but I am new to angular so didn't understood it well – Mathematics Aug 10 '16 at 08:32
2

I created a plunk from your code and it seems to be working fine. Just remember, it will generate a log only when validity state of your form changes from valid to invalid or vice versa.

https://plnkr.co/edit/lW3e4p

  <div ng-app="my-app">
    <div ng-controller="testCtrl">
      <div my-directive>
         <form name="myForm">
           <input type="number" step="0.01" ng-model="rate" required>
         </form>
      </div>
    </div>
  </div>

Angular:

angular.module('my-app').directive('myDirective', function() {
  return {
    link: function(scope, element, attr, mCtrl) {
      scope.$watch('myForm.$valid', function(validity) {
        console.log(validity);
      })
    }
  };
});
Dev Shah
  • 302
  • 1
  • 7
  • Hi, I have a isolated scope, please check the plunker I added, sorry I should had mentioned it before but I am new to angular so didn't understood it well – Mathematics Aug 10 '16 at 08:32