15

I'm using ionic and I have the following view:

<ion-view hide-nav-bar="true" ng-controller="loginController" class="login-view">
  <ion-content class="padding">

    <div class="row row-center">
      <div class="col">

        <div id="logo"></div>

        <form>
          <div class="list">
            <label class="item item-input">
              <input type="text" placeholder="Membership No" ng-model="membershipNo">
            </label>
            <label class="item item-input">
              <input type="password" placeholder="Password" ng-model="password">
            </label>
          </div>

          <button class="button button-block button-positive button-login" ng-click="login()">
            Login
          </button>
        </form>

      </div>
    </div>

  </ion-content>
</ion-view>

And my controller:

app.controller('loginController', ['$scope', '$localstorage',
    function($scope, $localstorage) {

        $scope.membershipNo;
        $scope.password;

        $scope.login = function () {
            console.log("User logged in with membership no: " + $scope.membershipNo +
    "\n and password: " + $scope.password);
        }

    }
]);

What I don't understand, is that when I click the button, the login function is called correctly. Also, if in the controller I go and set $scope.membershipNo to something like "Banana Pancake", the view actually updates.

Yet when the login function actually runs, is says that membershipNo and password are undefined. I'm fairly new to Angular and Ionic so I know this is probably some n00b mistake...

MHX
  • 1,581
  • 2
  • 21
  • 31
  • 5
    You're binding to a primitive. Don't do that. http://www.codelord.net/2014/05/10/understanding-angulars-magic-dont-bind-to-primitives/ (Essentially, the value of `membershipNo` is being passed by value, so what's being changed is not the reference in the controller. Create an Object, something like `$scope.user = {}` and pass that `ng-model="user.membershipNo"`, otherwise Angular cannot send data back to the controller...) – DRobinson Aug 13 '15 at 12:47
  • possible duplicate of [Ng-model does not update controller value](http://stackoverflow.com/questions/12618342/ng-model-does-not-update-controller-value) – DRobinson Aug 13 '15 at 12:48
  • The problem is somewhere else maybe, because it appears to work fine here http://plnkr.co/edit/L0ip3gShFcteiFdUBtlR?p=preview – Rahil Wazir Aug 13 '15 at 12:49
  • 2
    What @DRobinson said. You can avoid that by using controllerAs-syntax, also making your code more elegant and future-proof in the process :-) – LionC Aug 13 '15 at 12:51
  • @DRobinson Thats not true for OP, primitive values should work just fine, unless being updated from nested scope. The article you linked is also referring to nested scope issue where primitive values fail to update – Rahil Wazir Aug 13 '15 at 12:57
  • 1
    @Rahil that only works if nothing between the `ngController` and the `ngModel` creates a new scope. It's very bad practice. You really want "dots" in your `ngModel`, every time. _Always_. http://stackoverflow.com/a/17186640/624590 (It also won't work for Dean because `ionContent` creates a scope.) – DRobinson Aug 13 '15 at 12:58
  • @DRobinson Yes thats it `ion-content` was creating a new scope – Rahil Wazir Aug 13 '15 at 12:59
  • 1
    I once owned a tele-scope as a kid but it never really could see very far. It did look cool though standing in my room. –  Aug 13 '15 at 13:01
  • @Rahil - Which is why you want a "dot" every time. If you're writing code, you generally want it to be predictable and extensible. Assuming that "you'll never put a scope between X and Y" is bad practice. Even if `ionContent` were not there, it's easy to imagine many scenarios where a scope would be added between the two - the developer that adds that new scoping directive should not have to worry about bad binding choices made to children directives. – DRobinson Aug 13 '15 at 13:01

5 Answers5

42

I had exact the same issue recently and that's probably a solution: https://stackoverflow.com/a/22768720/552936

Modified quote:

"If you use ng-model, you have to have a dot in there."
Make your model point to an object.property and you'll be good to go.

Controller

$scope.formData = {};
$scope.login = function () {
  console.log("User logged in with membership no: " + $scope.formData.membershipNo +
  "\n and password: " + $scope.formData.password);
 }

Template

<input type="text" placeholder="Membership No" ng-model="formData.membershipNo">
<input type="password" placeholder="Password" ng-model="formData.password">
Community
  • 1
  • 1
mbajur
  • 4,406
  • 5
  • 49
  • 79
  • 2
    Though this will resolve the issue, it doesn't really provide an answer why it failed in the first place. – skubski Aug 13 '15 at 12:56
  • 3
    Just like @DRobinson said and like your example above shows, I took membershipNo and password and wrapped them in a 'credentials' object and now magically everything works.. but WHY!? –  Aug 13 '15 at 12:57
  • I am also curious as to the why of this. I have other variables that work fine not being in an object – BelgoCanadian Jun 25 '21 at 00:09
3

Please check this code This is worked for me:

<div class="row row-center">
  <div class="col">

    <div id="logo"></div>

    <form>
      <div class="list">
        <label class="item item-input">
          <input type="text" placeholder="Membership No" ng-model="data.membershipNo">
        </label>
        <label class="item item-input">
          <input type="password" placeholder="Password" ng-model="data.password">
        </label>
      </div>

      <button class="button button-block button-positive button-login" ng-click="login()">
        Login
      </button>
    </form>

  </div>
</div>

and in your-controller:

app.controller('loginController', ['$scope',
  function($scope) {
    $scope.data={};
  $scope.login = function () {
    console.log("User logged in with membership no: " + $scope.data.membershipNo +
    "\n and password: " + $scope.data.password);
  }

}]);
Anil kumar
  • 930
  • 7
  • 18
2

You need to define your $scope variables like this in your controller:

$scope.membershipNo = '';
$scope.password = '';

So your controller would look like:

app.controller('loginController', ['$scope', '$localstorage',
  function($scope, $localstorage) {

  $scope.membershipNo = '';
  $scope.password = '';
  $scope.login = function () {
    console.log("User logged in with membership no: " + $scope.membershipNo +
    "\n and password: " + $scope.password);
  }

}]);
MHX
  • 1,581
  • 2
  • 21
  • 31
  • I did try that, then the function prints out just blank values and not actually what the user entered...? –  Aug 13 '15 at 12:47
1

Hey Jean,Have a look of it your code is working here

       <ion-view ng-app="app" hide-nav-bar="true" ng-controller="loginController" class="login-view">
      <ion-content class="padding">

        <div class="row row-center">
          <div class="col">

            <div id="logo"></div>

            <form>
              <div class="list">
                <label class="item item-input">
                  <input type="text" placeholder="Membership No" ng-model="membershipNo">
                </label>
                <label class="item item-input">
                  <input type="password" placeholder="Password" ng-model="password">
                </label>
              </div>

              <button class="button button-block button-positive button-login" ng-click="login()">
                Login
              </button>
            </form>

          </div>
        </div>

      </ion-content>
    </ion-view> 


var app= angular.module("app",[]);
    app.controller('loginController', ['$scope', 
      function($scope, $localstorage) {

      $scope.membershipNo;
      $scope.password;
      $scope.login = function () {
        alert("User logged in with membership no: " + ($scope.membershipNo || '') +
        "\n and password: " + ($scope.password || ''));
      }

    }]);
Akshay Dhankhar
  • 274
  • 1
  • 6
  • could you add an explanation helping the "asker" to understand what you've done and why - so that we can all learn from it – ry8806 Aug 13 '15 at 13:33
  • Hi Ry8806, It's a concept of typical inheritance. As the @mbajur make in his example by making a object of it. It is pattern in javascript that angularjs used. If the heirarchies used in you code like realtion between child scopes & parent scopes are maintained properly then there should be no issues in that. Else you get these type of issue in angularjs of losing the scope properties value. But if you can see i just make a simple controller then it's work properly. And i don't know the exact thing what jean wants to do. But in code snippet he added is having no issue. – Akshay Dhankhar Aug 13 '15 at 19:09
0
$scope.user = {};
$scope.submitForm = function (isValid) {
   if (($scope.user.name || '').length > 0){ //Code }
}
Hakan
  • 1,199
  • 1
  • 14
  • 18