Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them, it only takes a minute:

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"

share|improve this question

2 Answers 2

up vote 0 down vote accepted

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"
share|improve this answer
    
Hi Radim, Thanks for your answer but I made a mistake when I have posted my question : in fact i want to show in console $scope.email.length As you said, it must be on $scope but I have same error message "canno't read property ...." if i try to use $scope.email.length Thanks again; – Developppeur Mar 28 at 16:35
    
I updated my answer - but even with email - my answer will be valid. I would suggest to init your Model = {} and set values which we can pre-set. In case we cannot (they must be provided by User input), we should always check if there is not null or undefined value if($scope.Model.email)... hope it helps – Radim Köhler Mar 28 at 17:41
1  
I replace ng-model="email" by ng-model="Model.email" in login.html And login.js : $scope.Model = {}; $scope.Model.email= "init value"; $scope.giveClass = function() { if($scope.Model.email){ console.log($scope.Model.email.length); } } So, now the field is fullfill with "init value" but when I change it nothing appear in the console, like one-way binding, PS : I change input type="email" by input type="text" and it's work but I want to keep input type="email" is it possible ? Thanks for your help, – Developppeur Mar 28 at 23:03

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>
share|improve this answer
    
Great job. Good to see that all... – Radim Köhler Mar 29 at 5:40

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.