OnsenUI | Passing Data Between Pages

Written by on May 16, 2015

OnsenUI | Passing Data Between Pages

Manual Data Sharing Between Controllers

Usually, we don’t want automatic updates between controllers. Some date needs to be accessed only during some situations. This solution requires a little bit different approach than the last example.

Example

Demo

Embeded working example
Manual 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>
      <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;">
        <h2>Sum of numbers is: {{parseInt(input.firstNumber) + parseInt(input.secondNumber)}}</h2>
      </ons-row>  

      <ons-row class="profile-wrapper" style="padding: 10px;">
        <button class="button button--large--cta" ng-click="getData()">Calculate mathematic operation</button>
      </ons-row>  

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

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

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

    var calculation = {};

    return {
        getCalcObject: function () {
            return calculation;
        },
        setCalcObject: function (calcObject) {
            calculation = calcObject;
        }
    };
    
});

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

  $scope.input = {};   
  $scope.input.firstNumber = 0;  
  $scope.input.secondNumber = 5;  

  Calculation.setCalcObject($scope.input);

  $scope.$watch('input', function (newValue, oldValue) {
      if (newValue !== oldValue) Calculation.setCalcObject(newValue);
  }, true); 

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

module.controller('ViewCtrl', function($scope, Calculation) {
  
  $scope.input = {};  
  $scope.parseInt = parseInt;

  $scope.getData = function(){
    $scope.input = Calculation.getCalcObject();
  }  
  
  $scope.goBack = function(){
    app.navi.popPage();
  }     
});

In this example, factory service uses getter and setter functions to acquire/modify inner object called calculation. If input elements values are modified that change will be propagated to $scope.input object. At the same time application is watching that same object looking for changes:

  $scope.$watch('input', function (newValue, oldValue) {
      if (newValue !== oldValue) Calculation.setCalcObject(newValue);
  }, true);  

The watch() function creates a watch of some variable. When you register a watch you pass two functions as parameters to the $watch() function. First one is a value function we’re watching and the second one is a listener function. The listener function should do whatever it needs to do if the value has changed. It also accepts newValue and oldValue as parameters.

We can compare these parameters and if there’s a difference between them we will send changed value (in our case object) to Factory service. Notice one more thing, $watch() function also accepts a third boolean parameter. This third parameter is used only if we’re comparing objects, you don’t need it if you’re watching primitive variables.

Next page has only one button:

<ons-row class="profile-wrapper" style="padding: 10px;">
    <button class="button button--large--cta" ng-click="getData()">Calculate mathematic operation</button>
</ons-row> 

When cliked this button will trigger function getData(), which will in result retrieve calculation object from a Factory service and set it to $scope.input variable.

$scope.getData = function(){
    $scope.input = Calculation.getCalcObject();
}  

You don’t need to use click event, anything can server as a trigger.

Sharing Data During Page Transitions

Sometimes we only need to pass data between controllers. This data does not need to be remembered, only processed on successful page transition. Excellent example would be Master-Detail pattern where Master list point to Detail page holding only selected list element data (usually expanded data set not seen on a list element). If you want to find out more about this structure pattern take a look at one of my previous tutorials.

Example

Demo

Embeded working example
OnsenUI Detail Pattern

I will not talk about this example here. Read my previously mentioned tutorial (Tutorial 5 – Master Detail Pattern) if you want to find more.

Who Am I?

Between working as a senior Java developer in one of the largest insurance companies in the world and traveling, in my free time, I work as a professional mobile development adviser. I'm also a major jQuery Mobile supporter back at StackOverflow and a forum moderator at the official Ionic Framework forum.



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