OnsenUI | Working With Navigation Pattern

Written by on April 9, 2015

OnsenUI | Working With Navigation Pattern

Because this input has an AngularJS attribute ng-model=”movie.name” everything we write will be bound to the $scope object movie:

  $scope.movie = {
    name: ''
  }

Another important thing about this input box is, each time we change something it will trigger change event bound to this input box (ng-change=”searchMovieDB()”). This event will trigger function searchMovieDB which is part of a List controller (ListCtrl):

$scope.searchMovieDB = function() {

This is where things get a little bit complicated. This function will call another function which is part of a factory service called Movies. This :

Movies.list($scope.movie.name, function(movies) {

will call this:

list: getData,

which is a part of a Movies factory service. AngularJS factory lets you create a service that you can use with AngularJS dependency injection. This is recommended way of exposing data from the server to the Angular views. In a few words, dependency injection is a software design pattern in which an object is given its dependencies, rather than the object creating them itself. It is about removing the hard-coded dependencies and making it possible to change them whenever needed. Don’t worry if you don’t understand a word I’m saying, you will learn it sooner or later.

Movies factory function list will accept two parameters, a first one is movie name and second one is an anonymous callback function we will use to acquire a list of searched movies. Function list will call another function getData:

function getData(moviename, callback) {

This function will in turn initiate a REST call to moviedb service, acquire a list of movies and returning it back to the original scope using passed callback function. It will set original scope object $scope.movies, which will in turn trigger list template population:

        <ons-list-item modifier="chevron" class="list-item-container" ng-repeat="movie in movies" ng-click="showDetail(movie.id)">
           
          <ons-row>
            <ons-col width="95px">
              <img ng-src="https://image.tmdb.org/t/p/w92{{movie.poster_path}}" onerror="this.src = 'https://www.ginesisnatural.com/images/no_image.jpg';" class="thumbnail">
            </ons-col>
            <ons-col>
              <div class="name">{{movie.original_title}}</div>
              <div class="desc">{{movie.release_date}}</div>
            </ons-col>
            <ons-col width="40px"></ons-col>
          </ons-row> 
           
        </ons-list-item>
         
      </ons-list> 

Attribute ng-repeat=”movie in movies” will loop through the object movies and build page content using acquired JSON data and list template.

Here’s where we come to the next big thing. I already told you we will have two pages (two controllers). When we click on a listview element we want to go to the another page where we will be able to see additional movie details. Relationships between pages are set through click event bound to each list element:

ng-click="showDetail(movie.id)"

In this case we are calling a function inside a ListCtrl controller called showDetail and we are passing it an id value of selected movie. Function will in turn initialize page change to view.html sending with it selected movie id:

app.navi.pushPage("view.html", { animation: "lift", movieid: id });

I forgot to mention ons-navigator directive, it handles page navigation and history, similar in nature to AngularJS ngView directive. As a user navigates throughout your app, OnsenUI is able to keep track of their navigation history. By knowing their history, transitions between views correctly enter and exit using the platform’s transition style. This is what this navigation system serves for.

When application transitions to the view page it will gather specific movie data using object/parameter page.options.movieid we passed using navigation change function.

Acquired data will generate another page content, again using prepared template.

      <div class="columns">
          <div class="pin">
            
              <div class="pin-header">
                <img src="https://cdn0.iconfinder.com/data/icons/iconsweets2/40/movie_film.png">
                <h2>{{movie.original_title}}</h2>
                <p>{{movie.release_date}}</p>
              </div>   
            
              <img ng-src="https://image.tmdb.org/t/p/w92{{movie.poster_path}}" width="200px" />
              <p>
                Average Vote: <strong>{{movie.vote_average}}</strong> (Votes: {{movie.vote_count}})
              </p>
          </div>
      </div>

Unfortunatelly, OnsenUI don’t have a card directive so this one is manually made.

ViewCtrl will not initiate another REST call, we will used cached movie data:

cachedData = data.results;

That’s everything you need to know about this application. I hope this example will help you as much as possible. If you have additional questions please leave them in a comment section below.

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

Leave a Reply