Developppeur
Developppeur

Reputation: 49

Ionic / Angular JS - $scope issue : Cannot read property 'length' of undefined

I can't use $scope in ionic, it seems that's $scope is not working.

Let's see very simple example : App.js :

angular.module('TestApp', ['ionic','TestCtrl'])
.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
})
.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('login', {
        url: "/login",
        templateUrl: "views/login.html",
        controller : "login"   
    });
  $urlRouterProvider.otherwise('/login');
});

Login.js :

angular.module('TestCtrl',[])
.controller('login', function($scope,$rootScope) {
    $scope.giveClass = function() {
      console.log($scope.email.length);
    }
});

Index.html :

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">
    <script src="lib/ionic/js/ionic.bundle.js"></script>
    <script src="cordova.js"></script>
    <script src="js/app.js"></script>
    <script src="controllers/login.js"></script>
  </head>
  <body ng-app="TestApp">
    <ion-nav-view></ion-nav-view>
  </body>
</html>

Login.html :

<ion-view>
    <ion-header-bar  class="bar-calm">
    <h1 class="title" ng-model="test">Login</h1>
  </ion-header-bar>
  <ion-content>
    <form ng-submit="postLogin()"  name="loginForm">
        <div class="list list-inset">
            <label class="item item-input" ng-class="giveClass()">
                <i class="icon  icon-fixed-width ion-at placeholder-icon"></i>
                <input type="email" name="email" ng-model="email" placeholder="Veuillez entrer votre adresse email" required/>
            </label>
            <label class="item item-input">
                 <i class="icon ion-key  icon-fixed-width   placeholder-icon"></i>
                 <input type="password"  name="password" ng-model="password" placeholder="Veuillez entrer votre mot de passe" required/>
            </label>    
          <div class="list">
           <label class="item">
                <button class="button button-block button-positive" type="submit">Se connecter</button>
           </label>
           <label class="item">
             <button class="button button-block button-royal" type="submit">S'enregistrer</button>
           </label>
         </div>
        </div>
        </form>
    </ion-content>
</ion-view>

When I execute this application console (console.log(...) in login.js) return

"Cannot read property 'length' of undefined"

Upvotes: 2

Views: 9339

Answers (2)

Developppeur
Developppeur

Reputation: 49

Thanks to Radim, I need to use a dot in ng-model, as an object ,and input-type="mail" will bound only if email match to regexp

So working example is : Apps.js:

angular.module('TestApp', ['ionic','TestCtrl'])
.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
})
.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('login', {
        url: "/login",
        templateUrl: "views/login.html",
        controller : "login"   
    });
  $urlRouterProvider.otherwise('/login');
});

Login.js:

angular.module('TestCtrl',[])
.controller('login', function($scope,$rootScope) {
    $scope.Model = {};
    $scope.giveClass = function() {
       if($scope.Model.email){
            console.log($scope.email.length);
    }
});

Index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">
    <script src="lib/ionic/js/ionic.bundle.js"></script>
    <script src="cordova.js"></script>
    <script src="js/app.js"></script>
    <script src="controllers/login.js"></script>
  </head>
  <body ng-app="TestApp">
    <ion-nav-view></ion-nav-view>
  </body>
</html>

Login.html:

<ion-view>
    <ion-header-bar  class="bar-calm">
    <h1 class="title">Login</h1>
  </ion-header-bar>
  <ion-content>
    <form ng-submit="postLogin()"  name="loginForm">
        <div class="list list-inset">
            <label class="item item-input" ng-class="giveClass()">
                <i class="icon  icon-fixed-width ion-at placeholder-icon"></i>
                <input type="text" name="email" ng-model="Model.email" placeholder="Veuillez entrer votre adresse email" required/>
            </label>
            <label class="item item-input">
                 <i class="icon ion-key  icon-fixed-width   placeholder-icon"></i>
                 <input type="password"  name="password" ng-model="password" placeholder="Veuillez entrer votre mot de passe" required/>
            </label>    
          <div class="list">
           <label class="item">
                <button class="button button-block button-positive" type="submit">Se connecter</button>
           </label>
           <label class="item">
             <button class="button button-block button-royal" type="submit">S'enregistrer</button>
           </label>
         </div>
        </div>
        </form>
    </ion-content>
</ion-view>

Upvotes: 1

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123891

It is not sure, where you plan to set your model property email. I mean, the 'email', which you pass to the ng-model in the Login.html:

<ion-view>
    ...
    // here is expected model 'email'
    <input type="email" name="email" ng-model="email" 
        placeholder="Veuillez entrer votre adresse email" required/>
   ...

In case, that angular won't find it - it will create that, but on the $scope. And the scope will be the first param not the second here Login.js:

.controller('login', function($scope,$rootScope) {
    $scope.giveClass = function() {
      // here we can expect 'email' to be created for us
      // but not on $rootScope
      // it will be available on $scope
      console.log($rootScope.email.length);

So, that all means:

  • there is no explict set of the $rootScope.email
  • nor of the $scope.email
  • because we used ng-model="email" we can expect, that angular will create such property for us, but on $scope, not on $rootScope

And that all together will end up with

Cannot read property 'length' of undefined

if we use $rootScope.email.length, or even $scope.email.length. Both of these should be init first or checked if they exist:

Solution: the way to go would be to initiate such property test (it is not needed, but we know what is happening). And even better, to use some Model (and have a dot - check more here: Model in a modal window in angularjs is empty)

.controller('login', function($scope,$rootScope) {
     $scope.Model = {};
     // if possible - init it, 
     // $scope.Model.email= "init value";
     $scope.giveClass = function() {
        // if we need user to init that, 
        // we have to check if that value was set
        if($scope.Model.email){
            console.log($scope.email.length);
        }
     }

and the view

ng-model="Model.email"

Upvotes: 3

Related Questions