Gere
Gere

Reputation: 2184

Validation messages into Directive - AngularJS

I'm trying do a small reusable component in AngularJS using directives. I have made good progress but I have a problem with the validations. For example the required validation not working. I think is "binding" issue.

My HTML code: also in http://jsfiddle.net/pQwht/17/

<html ng-app="myApp">
<body>
<form ng-controller="Ctrl"
  id="paymentCallForm"
  action="#"
  name="paymentCallForm">
  <table>
   <tr tdfield 
      labelname="Primary Account Number:" 
      fieldname="primaryAccountNumber"
      title="Primary title" 
      >
    </tr>  
  </table>

My directive script:

 angular.module('myApp').directive('tdfield', function() {
    return {
    restrict: 'A',
    replace:false,
    transclude: false,
    scope: { labelname: '@', fieldname: '@', title: '@'},
    templateUrl:'element.html'
  };
 });

My element.html code:

 <td id="lbl_paymentReference" class="formInputLabelWrapper">{{labelname}}</td>
 <td class="formInputTextWrapper">
   <input id="{{fieldname}}"
     name="{{fieldname}}"
     title="{{title}}" 
     class="large empty"  
     required>
<span data-ng-show="paymentCallForm.{{fieldname}}.$error.required"
    class="error">Error</span></td>

Upvotes: 1

Views: 1800

Answers (2)

Yaroslav
Yaroslav

Reputation: 4669

Well, I solved this, but for what a price. There is a number of issues and angular related among them. I may not recall all, so here is the working example https://github.com/yaroslav-ulanovych/soq16245177.

When you define scope parameter like scope: { labelname: '@', fieldname: '@', title: '@'}, (with an object as a value), that creates an isolated scope, which means not inherited from parent one's. Therefore here ng-show="paymentCallForm.{{fieldname}}.$error.required" is no access to the form. As a workaround ng-show="$parent.paymentCallForm.{{fieldname}}.$error.required", but I didn't check whether your inputs are published in the form in case of the isolated scope. Or scope: true and inject attributes into the scope manually.

compile: function() {
    return {
        pre: function (scope, element, attr) {
            scope.fieldname = attr.fieldname;
        }
    }
}

Note on using prelink function, so that it's called before children are linked.

Next ng-show will actually use not interpolated expression and there is obviously no property named {{fieldname}} in the form. That is fixed in later versions of Angular, don't know when exactly, cause I'm using master.

But what is not fixed is ngModelController. It gets it's name very early so publishes itself on the form under wrong one. I had to fix that myself, good that there is only one line to do that, in file src/ng/directive/input.js.

// add
modelCtrl.$name = attr.name;
// before this
formCtrl.$addControl(modelCtrl);

Upvotes: 2

Ketan
Ketan

Reputation: 5891

I believe you need a controller attached to your view. The form object will be attached to property with the id of the form on $scope object of this controller. Once you add that, I think it will start showing up.

Upvotes: 0

Related Questions