2

I would like to create a directive which does something awesome with all the input fields within a form.

However, i'd be happy if i could apply that directive only once (to the <form> itself) instead of having it to bind to all the <input>'s

How should i determine all of a forms input elements?

I see some possible solutions:

element[0].childNodes  // filter all inputs
element[0].children
element[0].elements   // seems to contain nothing but the stuff i want

Maybe i am even to close-minded and don't see the correct solution here.

Any help and opion is appreciated

2 Answers 2

3

Warning: This is just an idea that works in a trivial example. I'm not saying it's wrong (this is open to discussion, though) but I have NOT used it in a more complicated context.

So... you can actually create a second input directive and have it applied only when another directive (let's say myDirective) has been applied to the enclosing form.

Suppose you have 2 forms:

<body>
    <form name="myForm1" ng-controller="MainCtrl">
      Name: <input id="name1" type="text" ng-model="data.name" /><br/>
      Surname: <input id="surname1" type="text" ng-model="data.surname" />
      <pre>{{data}}</pre>
    </form>
    <br/>
    <form name="myForm2" ng-controller="MainCtrl" my-directive>
      Name: <input id="name2" type="text" ng-model="data.name" /><br/>
      Surname: <input id="surname2" type="text" ng-model="data.surname" />
      <pre>{{data}}</pre>
    </form>
</body>

Only the second form is tagged with my-directive. Now, your directives could look like:

app.directive("myDirective", function(){
    return {
        restrict: 'A',
        require: ['form'],
        controller: function() {
          // nothing here
        },
        link: function(scope, ele, attrs, controllers){
          var formCtrl = controllers[0];
          console.log("myDirective applied to form:", formCtrl.$name);
        }
    };
});

app.directive("input", function(){
    return {
        restrict: 'E',
        priority: -1000,
        require: '^?myDirective',
        link: function(scope, ele, attrs, ctrl){
          if (ctrl) {
            console.log("applying custom behaviour to input: ", ele.attr('id'));
            // ... awesomeness here
          }
        }
    };
});

See it live and check out the logs. The original input directive lives side-by-side with your own. The proof for that is that the form still works (as you type, the model is updated: that's input's and then, ngModel's job).

Your input directive could also use ngModel to manipulate the input value:

app.directive("input", function(){
    return {
        restrict: 'E',
        priority: -1000,
        require: ['?ngModel', '^?myDirective'],
        link: function(scope, ele, attrs, ctrls){
          var ngModel = ctrls[0];
          var myDirective = ctrls[1];
          if (myDirective) {
            console.log("applying custom behaviour to input: ", ele.attr('id'));
            // ... awesomeness here
          }
        }
    };
});
Sign up to request clarification or add additional context in comments.

1 Comment

I like this approach. It does still have to bind to all the input elements, but conveniently, that happens without any additional tags. This wouldn't apply, for example, to a textarea element. Just something to keep in mind.
2

why not use Angular's jqLite (or jQuery if you choose to load it)

angular.forEach(element.find('input'), function(node){ 
 awesomize(node)
});

2 Comments

I still shudder when thinking about using jQuery stuff for an Angular application. Nevertheless, i'd give it a try, thank you for pointing out the obvious
you have to iterate the dom tree under <form> regardless, might as well do it in a semantically pleasant way(that is provided by angular)

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.