You will face this problem sooner or later. A code that works just fine in a standard AngularJS application will no longer work when packaged with Ionic Framework. It happened to me when I was working on my very first Ionic application, the very first day I was playing with it.
 
 

Note: If this tutorial was helpful, need further clarification, something is not working or do you have a request for another Ionic post? Furthermore, if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here, again leave me a comment below. I'm here to help you, I expect the same from you. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com, or follow and mention me on twitter (@gajotres). Thanks and have a nice day!

PS. If you want my help, if possible (even if it takes you some time to do that), create a working example I can play with. Use Plunker for AngularJS based questions or jsFiddle for jQuery/jQuery Mobile based questions.


 

Table of Contents

 
Click here if you want to see other tutorials, or articles about the Ionic framework (themes, templates, plugins, tutorials)
 

The Problem

 
I found this problem last night on StackOverflow, also solved it at the same time. Someone has created a simply number calculator; everything worked just fine except the process of number adding.
 
Working example:
 
Problem Example
 
 
So what’s happening here? The scope is working just fine but two-way binding is not working inside a function.
 

Introduction

 
In one of the most famous AngularJS meetup, one of the leading developers declared this:
 
..if you use ng-model there has to be a dot somewhere. If you don’t have a dot, you’re doing it wrong..Miško Hevery
 
So what is this dot and why is it so important?
 
AngularJS uses scope inheriting which should allow some child scope (for example a child controller) to see the properties of the parent scope.
 
Example:
 
<div ng-controller="MainController">
    <input type="text" ng-model="foo"/>
    <div ng-controller="ChildController">
        <input type="text" ng-model="foo"/>
    </div>
</div>
 
Initially, when you start this example and type something into the parent input, the child input will reflect these changes.
 
However, once you change something in the child input, you will sever the connection with the parent input, thus making them out of the sync.
 
If you change this example to look like this:
 
<div ng-controller="MainController">
    <input type="text" ng-model="foo.bar"/>
    <div ng-controller="ChildController">
        <input type="text" ng-model="foo.bar"/>
    </div>
</div>
Everything suddenly works just fine, in both directions.
 
The reason behind this is, the child scope uses prototypical inheritance when it tries to look up the value. So as long as it never gets set on the child, then it will defer to the parent scope. But, once it’s set, it will no longer look up at the parent.
 
In the case of our second example, When you instead replace a primitive variable with an object, nothing ever gets set on the child scope. Thus, the inheritance remains.
 
How does it reflect Ionic Framework? Ionic uses child scopes, and the scopes are isolated quite frequently. Because of this, two-way binding on primitives will often not work. That’s why we need to use “dot notation” with Ionic Framework.
 

Solution 1

 
What I said before is not absolute, we can still make it work without the “dot notation”.
 
Working example:
 
Solution 1
 
 

Code

HTML looks like this:
 
<!DOCTYPE html>
<html ng-app="myApp">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
  <title>Ionic Framework Example</title>
  <link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet" />
  <script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
  <script src="app.js"></script>
</head>

<body>

  <ion-pane>


    <ion-content ng-controller="CalculatorCtrl">

      <div class="row">
        <div class="col description">En la regla de tres, se establece la relación de proporcionalidad entre dos valores conocidos, por ejemplo: A y B, y conociendo un tercer valor X, podemos calcular un cuarto valor Y.
        </div>
      </div>

      <div id="calculator-div">

        <div class="row">
          <div class="col" id="calculator-title">Calcular Y</div>
        </div>

        <div class="row">

          <div class="col">
            <label class="item item-input item-floating-label">
              <input type="number" placeholder="{{a}}" ng-model="a">
            </label>
          </div>

          <div class="col col-10 ion-arrow-right-b"></div>

          <div class="col">
            <label class="item item-input item-floating-label">
              <input type="number" placeholder="{{x}}" ng-model="x">
            </label>
          </div>

        </div>

        <div class="row">

          <div class="col">
            <label class="item item-input item-floating-label">
              <input type="number" placeholder="{{b}}" ng-model="b">
            </label>
          </div>

          <div class="col col-10 ion-arrow-right-b"></div>

          <div class="col">
            <label class="item item-positive item-floating-label" id="result">
              {{result()}}
            </label>
          </div>

        </div>
      </div>

      <div class="row">

        <div class="col">

          <p>Si necesito {{x}} zanahorias para alimentar {{a}} conejos, ¿cuántas zanahorias necesito para alimentar {{b}} conejos?</p>

          A= {{a}} B= {{b}} X= {{x}}
        </div>
      </div>

    </ion-content>

  </ion-pane>

</body>

</html>
 
JavaScript looks like this:
 
angular.module('myApp', ['ionic'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if (window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if (window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
})

//=========================================================================


.controller('CalculatorCtrl', function($scope) {

  $scope.a = 0;
  $scope.b = 0;
  $scope.x = 0;
  $scope.u = 0;

  $scope.result = function() {
    console.log($scope.a);
    $scope.u = $scope.a + $scope.b + $scope.x;
    return $scope.u;
  }

});
 
As you can see, the JavaScript part looks the same like in the original example. There’s only one difference, ng-controller is now moved to the ion-content directive.
 
Continue Reading

  • MichaelR

    Excellent article. I ran into this issue early on and had no idea what I was doing wrong. I had read a quick post on forum somewhere about adding a dot and a property, but I never understood why until now. Love the blog by the way. You have consistently posted some of the most informative and valuable content and have helped me many times over.