Make Form controller available inside directive?

3,890 views
Skip to first unread message

jfyo...@gmail.com

unread,
Jul 13, 2012, 12:11:39 PM7/13/12
to ang...@googlegroups.com
Hi guys, here is what I'm trying to do.

<form name="myForm">
    <myinput field="firstName" caption="First Name"  wrapper-class="little" size="big" icon-kind="add" value="firstName" ></myinput>       
</form>

myinput is a directive that contains an html input. I'm trying to run validation on that input.
This span is inside the myinput directive.
<span class="error help-inline" ng-show="myForm.firstName.$error.required"> Required!</span>
But inside the directive it doesn't know what myForm is. So how can I either pass the form object to the directive or have the directive use the form's scope.

Thanks,

Judd

David Krutky

unread,
Aug 20, 2012, 5:23:33 AM8/20/12
to ang...@googlegroups.com, jfyo...@gmail.com
You can try to pass it as an argument to directive like this:

<form name="myForm">
    <myinput form="myForm" field="firstName" caption="First Name"  wrapper-class="little" size="big" icon-kind="add" value="firstName" ></myinput>        
</form>

and then in directive scope you create two way binding:

function myinput() {
    return {
    restrict: 'E',
    scope: {
    form: '=',
    },
}

Now you can access the myForm variable in directive code for exapmle like this: 

scope.form.firstName.$error.required

jon....@gmail.com

unread,
Aug 23, 2012, 4:07:46 PM8/23/12
to ang...@googlegroups.com, jfyo...@gmail.com
Did you get this working? Here is my naive attempt at it:

<script type="text/ng-template" id="/partials/form-input.html">
    <div class="control-group" ng-class="{error: form[name].$invalid}">
        <label class="control-label" for="{{name}}">{{label}}</label>
<div class="controls">
<input type="text" name="*DON'T KNOW WHAT TO PUT HERE*" class="input-xlarge" ng-model=model required></input>
<span ng-show="form[name].$error.required" class="help-inline">Required</span>
</div>
    </div>
</script>

And a directive that looks like this:

myLab.directives.directive('formInput', function() {
return {
restrict: 'E',
replace: true,
scope: {
label: '@',
name: '@',
form: '=',
model: '='
},
templateUrl: '/partials/form-input.html'
}
});

then invoked like this:
<form-input form="myForm" name="myField" label="Some Field" model="model.myProperty">

Not sure how to properly apply the name attribute to the input control so that it will get registered properly. It works fine if I hard-code the name attribute to "myField" in the directive but of course this isn't very useful ;). Do I need to hack something in during the compile like Misko showed here: http://stackoverflow.com/questions/10629238/angularjs-customizing-the-template-within-a-directive ?

Thanks,
Jon

jon....@gmail.com

unread,
Aug 23, 2012, 4:52:11 PM8/23/12
to ang...@googlegroups.com, jfyo...@gmail.com
Hacked something into the compile function and it works.

compile: function(element, attrs){
     element.find("input")[0].setAttribute('name',attrs.name);
}

Would like to know if anyone has managed to successfully do this template more cleanly, though. 

David Krutky

unread,
Aug 29, 2012, 7:29:26 AM8/29/12
to ang...@googlegroups.com, jfyo...@gmail.com, jon....@gmail.com
I don't think it's possible to make it cleaner than you have it now. Maybe instead of doing it in the compile function of the whole directive, create a new separative directive for that, restrict it for attribute and do the same code there. Like this:

<div class="controls">
<input type="text" form-name="{{name}}" class="input-xlarge" ng-model=model required></input>
<span ng-show="form[name].$error.required" class="help-inline">Required</span>
</div>

myLab.directives.directive('formName', function() {
return {
restrict: 'A',
                compile: function(element, attrs){
                       element.attr('name', attrs.name);
                }
}
});

Jonathan Card

unread,
Aug 30, 2012, 9:31:01 AM8/30/12
to David Krutky, ang...@googlegroups.com, jfyo...@gmail.com
Thanks for the idea! Since I didn't like having to feed the form name through every time I ended up avoiding the issue by adding a controller to the directive that resolves the nearest form controller. The line for this was stolen shamelessly from the angular FormController code itself (they use it to find parent forms):

    myLab.directives.directive('formInput', function() {
        return {
            restrict : 'E',
            ...,
            templateUrl : '/partials/form-input.html',
            controller : function($scope, $element){
                $scope.form = $element.parent().controller('form');
Reply all
Reply to author
Forward
0 new messages