OnsenUI | Passing Data Between Pages

Written by on May 16, 2015

OnsenUI | Passing Data Between Pages

It just dawned on me, in all of my tutorials I never talked about passing data between application pages. Experienced users will not think twice about this topic, though is can be an unpassable mountain for beginners. I remember my time spent at StackOverflow helping newly introduced jQuery Mobile developers, this was a constant topic.

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

Table of Contents

[spoiler title=” Click here if you want to see other tutorials, this is the 9th tutorial out of 12 total.”]

[/spoiler]

Automatic Data Sharing Between Controllers

This solution is all about automatic data sharing while your application is alive and kicking. You will learn how to broadcast messages using Factory services so that data can be shared between controllers.

This approach is useful when you have multiple controllers on one page or multiple pages, and all controllers (or some of then) needs to know when data managed by another controller has been changed. Excellent example would be storing settings data that have application-wide implications.

Example

Demo

Embeded working example
Automatic Data Sharing Between Controllers

HTML
<html>

<head>
  <script src="https://code.angularjs.org/1.3.0/angular.js"></script>
  <script src="http://onsenui.io/OnsenUI/build/js/onsenui.js"></script>
  <script src="script.js"></script>
  <link rel="stylesheet" href="https://cdn.rawgit.com/OnsenUI/OnsenUI/1.2.2/build/css/onsenui.css" />
  <link rel="stylesheet" href="https://cdn.rawgit.com/OnsenUI/OnsenUI/1.2.2/build/css/onsen-css-components.css" />
</head>

<body ng-controller="ListCtrl">

  <ons-navigator animation="slide" var="app.navi">
    <ons-page>
      <ons-toolbar class="toolbar-black">
        <div class="center">First Page</div>
      </ons-toolbar>
      <h2 style="text-align: center;">Session Wide Sharing Between Controllers</h2><br/>
      <h5 style="text-align: center;">Enter numbers into input boxes and go to the next page</h5><br/>   
      <ul class="list">
        <li class="list__header">Enter First Number</li>
      </ul>
      <input type="number" class="text-input text-input--underbar" placeholder="Enter first number" value=""  ng-model="input.firstNumber" style="width: 96%; margin: 2%;">
      <ul class="list">
        <li class="list__header">Enter Second Number</li>
      </ul>      
      <input type="number" class="text-input text-input--underbar" placeholder="Enter second number" value="" ng-model="input.secondNumber" style="width: 96%; margin: 2%;">
      <ons-row class="profile-wrapper" style="padding: 10px;">
        <button class="button button--large--cta" ng-click="changePageWithAnimation()">Add up the numbers</button>
      </ons-row>    
     
    </ons-page>   
  </ons-navigator>    
   
  <ons-template id="view.html">
    <ons-page ng-controller="ViewCtrl">
      <ons-toolbar>
        <div class="left" style="line-height: 44px">
          <ons-back-button>Back</ons-back-button>
        </div>        
        <div class="center">Second Page</div>
      </ons-toolbar>

      <ons-row class="profile-wrapper" style="padding: 10px;">
        <button class="button button--large--cta" ng-click="goBack()">Go Back</button>
      </ons-row>  

      <ons-row class="profile-wrapper" style="padding: 10px;">
        <h2>Sum of numbers is: {{parseInt(input.firstNumber) + parseInt(input.secondNumber)}}</h2>
      </ons-row>  

    </ons-page>
  </ons-template>
  
</body>
</html>
JavaScript
var module = ons.bootstrap('my-app', ['onsen']);

module.factory('Calculation', function() {

  calculation = {};
  calculation.firstNumber = 0;
  calculation.secondNumber = 0;  
  return calculation;
});


module.controller('ListCtrl', function($scope, Calculation) {

  $scope.input = Calculation;  

  $scope.changePageWithAnimation = function(){
    app.navi.pushPage("view.html", { animation: "lift"});
  }    
});

module.controller('ViewCtrl', function($scope, Calculation) {
  
  $scope.input = Calculation;    
  $scope.parseInt = parseInt;
  
  var page = app.navi.getCurrentPage();
  console.log(page.options.movieid);
  
  $scope.goBack = function(){
    app.navi.popPage();
  }     
});

Overview

This solution uses Factory service as data storage. This Calculation factory service can be injected into each of the controllers as a parameter. This way, we are now attaching the $scope.input to an application service, which serves as the binding point between the two controller models.

Provided example has two controllers, one for every page.

First Controller:

module.controller('ListCtrl',  .......

Second Controller:

module.controller('ViewCtrl', ........

We also need a Factory service to share data between controllers:

module.factory('Calculation', function() {
    //other Calculation factory related code
});

Now, we need to inject this factory inside both controllers and set a scope variable called $scope.input which will store out calculation information:

module.controller('ListCtrl', function($scope, Calculation) {

  $scope.input = Calculation;  
  //other ListCtrl related code
});

module.controller('ViewCtrl', function($scope, Calculation) {
  
  $scope.input = Calculation;   
  //other ViewCtrl related code
});

This way both controllers $scope.input objects will be injected with a reference to the Calculation factory. In the end, change to one controller input object will propagate to the other controller. One last thing, take a look at this line:

$scope.parseInt = parseInt;

You can’t use JavaScript functions inside an expression, this is a workaround. Basically if you add a function to scope it will be also available inside expression, like this:

<h2>Sum of numbers is: {{parseInt(input.firstNumber) + parseInt(input.secondNumber)}}</h2>

Continue Reading

Categories

4 thoughts on “OnsenUI | Passing Data Between Pages”

  1. Hello, I really appreciate all your work. I am trying to follow all your articles about Onsen UI, but notice that the first Html example about data sharing between pages was given using Ionic framework. Am I missing something here? Thanks!
    Zjiang

  2. Hi! I think something changed in version 2 (now it’s RC 6).
    There is now `getCurrentPage` and I found `nav.topPage.pushedOptions` as a detour to achieve my goal.

Leave a Reply