jolynice
jolynice

Reputation: 544

Why my angular controller don´t find my form - $scope.form undefined

I am trying do understand why my form is not recognize inside the maincontroller, if I put another controller outside, my form is recognize.

config.js

var myApp = angular.module('Myapp', ['ui.router','oc.lazyLoad','ui.bootstrap','kendo.directives','ngStorage',]);

function config($stateProvider, $urlRouterProvider, $ocLazyLoadProvider) {
    $urlRouterProvider.otherwise("/index/main");
    $stateProvider
        .state('testing', {
            url: "/testing",
            controller: 'MyController',
            templateUrl: "testing.html"
        });
}

angular
    .module('Myapp')
    .config(config)
    .run(function($rootScope, $state) {
        $rootScope.$state = $state;
    }); 

MyController.js

function MyController($scope) {     
  //do something
  $scope.test = {name: 'das'};

    $scope.sendTest = function () {
        console.log($scope.form.$valid);
        console.log($scope.form.testNumber.$valid);
        console.log($scope.form.testName.$valid);
    };
};

angular
    .module('Myapp')
    .controller('MyController', ["$scope"]);

testing.html

<form name="form" novalidate>
    <p>
        <label>Number: </label>
        <input type="number" min="0" max="10" ng-model="test.number" name="testNumber" required />
    </p>
    <p>
        <label>Name: </label>
        <input type="text" ng-model="test.name" name="testName" required />
    </p>
    <button ng-click="sendTest()">Submit</button>
</form> 

Like this a have this error

TypeError: Cannot read property '$valid' of undefined

but if I create another controller inside MyController.js and i move the code inside like this

function ChildController($scope,$timeout) {
    $scope.test = {
        name: 'das'
    };

    $scope.sendTest = function () {
        console.log($scope.form.$valid);
        console.log($scope.form.testNumber.$valid);
        console.log($scope.form.testName.$valid);
    };
};

function MyController($scope) {  //do other stuff ...};


angular
    .module('Myapp')
    .controller('ChildController', ["$scope", ChildController])
    .controller('MyController', ["$scope"]);

and add the ng-controller to the form like this

<form name="form" novalidate ng-controller='ChildController'>

the form is reconize correctly and working.

Can anyone explain what I am missing here, i would like to understand better, I am a novice.

Thanks you for the help.

Best regards. Jolynice

Upvotes: 2

Views: 4109

Answers (2)

Sabarish S A
Sabarish S A

Reputation: 11

Check whether if the form is inside any div which has ng-if condition Like

<div ng-if="condition">
  <form name="viewCtrl.form">
   .
  </form>
</div>

If this is so, the form would return undefined since there is new scope created for the DOM containing ng-if condition. Then use ng-show instead of ng-if that would not create new scope. I got this solution from this answer

Upvotes: 1

Sean Larkin
Sean Larkin

Reputation: 6420

As seen in Brad Barber's comment:

The form is being created on the child scope and not the controller scope.

A good solution like he suggested would be to add the bindToController and controllerAs syntax to your route object:

function config($stateProvider, $urlRouterProvider, $ocLazyLoadProvider) {
    $urlRouterProvider.otherwise("/index/main");
    $stateProvider
        .state('testing', {
            url: "/testing",
            controller: 'MyController',
            controllerAs: 'viewCtrl',
            bindToController: 'true',
            templateUrl: "testing.html"
        });
}

Now you can bind the name of the form as viewCtrl.form:

<form name="viewCtrl.form" novalidate>
    <p>
        <label>Number: </label>
        <input type="number" min="0" max="10" ng-model="viewCtrl.test.number" name="testNumber" required />
    </p>
    <p>
        <label>Name: </label>
        <input type="text" ng-model="viewCtrl.test.name" name="testName" required />
    </p>
    <button ng-click="viewCtrl.sendTest()">Submit</button>
</form> 

You can then notate it in your controller using this:

function MyController($scope) {     
  // Adding variables functions available to ctrl scope
  // same as vm = this;
  angular.extend(this, {
    test: {name: 'das'},
    sendTest: function() {
       console.log(this.form.$valid);
       console.log(this.form.testNumber.$valid);
       console.log(this.form.testName.$valid);
    }
  });

};

angular
    .module('Myapp')
    .controller('MyController', ["$scope", MyController]);

Here is a codepen that I hacked together for you:

Upvotes: 1

Related Questions