hopsey
hopsey

Reputation: 1513

AngularJS - form inside ng-repeat undefined in controller

I'm trying to access form object in my controller. Form lies inside ng-repeat block it has got its dynamic name and I should be able to access it since v1.3.

js:

var app = angular.module('app', []);
app.controller('AppCtrl', ['$scope', function($scope) {
  $scope.forms = [0];
  $scope.testForm = function() {
    if($scope.form0 == undefined) {
      $scope.test = 'Form is NOT defined';
    } else {
      $scope.test = 'Form is defined';
    }
  }
}])

html:

<body ng-app="app">
  <div ng-controller="AppCtrl">
    <div ng-repeat="form in forms" ng-init="formName = 'form' + $index">
      form name should be {{formName}}
      <form name="{{formName}}">
        <input type="text" name="field" />
      </form>
    </div>
  <button ng-click="testForm()">Check if form exists</button>
  <p ng-bind="test"></p>
  </div>
</body>

But in my controller $scope.form0 is undefined - after clicking "Check if form exists" I get "Form is NOT defined" message. Even if I give it a static name (<form name="form0">) I still keep getting undefined. When I take form out of the ng-repeat loop, it works fine.

Any idea why it is not set?

The example above: https://plnkr.co/edit/Fvy5LdIO0H1vCS9wYR0U?p=preview

Thanks in advance!

Upvotes: 1

Views: 993

Answers (1)

MMhunter
MMhunter

Reputation: 1441

This is because ng-repeat is creating isolated child scopes, the form0 is in the child scope and not visible from the parent (the controller's scope).

So the solution is to pass it to the parent. However we cannot do it in ng-init since the form controller is not initialised by that time.

One approach I could think of is having a custom directive to bind the formController to a specified scope.

app.directive("form",function($parse){
  return{
    restrict:"E",
    priority:-1,
    link:function(scope,ele,attrs){
      var targetScope = $parse(attrs.bindToScope)(scope);
      if(targetScope){
        targetScope[attrs.name] = scope[attrs.name];
      }
    }
  }
})

and with this we can tell the form to bind the controller to the scope we specified.

<form name="{{formName}}" bind-to-scope='$parent' >
     <input type="text" name="field" />
</form>

Upvotes: 3

Related Questions