Ionic: Master Detail Pattern

posted in: Uncategorized | 25

“I have a list. What I want is when I click on one of the item of List a new page should open where the data related to only that listItem is displayed. … I know about .service but I can’t figure out a way to pass data specific to the item clicked.”

What this user is asking about is the classic master detail pattern that you indeed would want to use a service (or factory) for.

Master Detail Interface

A Master Detail Interface is a common pattern in computer systems where a master list is displayed, and when an item is selected, more details about that item are displayed in a separate view. This can be found all over the place from a contact list (list of contacts being the master list, clicking on a contact shows you the “details” of that contact) to a text messages app, to search results.

In Ionic and Angular, this is typically achieved through the help of a service (or factory) and $stateParams. The idea is to save the results of a master list to a private variable in the service and access an individual item from that array through a method of the service.

Example

For our example, we’ll be working with two templates, 2 controllers, a config, and a factory. We’ll create a master list of people and when you click on each person, it will display the details of that person.

Views

We’ll be working with two views: master.html and details.html.

master:

<ion-view title="Master List">
	<ion-content>
		<ion-list>
			<ion-item class="item" ng-repeat="person in people">
				<a href="#/details/{{person.id}}">{{person.firstName}} {{person.lastName}}</a>
			</ion-item>
		</ion-list>
	</ion-content>
</ion-view>

Pretty simple, just looping through an array of person, call people, and creating links to the details view, passing in the id in the url.

details:

<ion-view title="Master List">
	<ion-content>
		<h2>{{person.firstName}} {{person.lastName}}</h2>
		<p>{{person.bio}}</p>
	</ion-content>
</ion-view>

Again, a simple view displaying more details about a person.

Config

We need to set up our router to accept the parameter in the URL for the details view. I am going to use the built in $stateProvider which is the angular-ui router that is shipped with Ionic.

.config(['$stateProvider',function($stateProvider) {
	$stateProvider
	.state('master', {
		url: "/masterList",
		templateUrl: 'templates/master.html',
		controller: 'masterCtrl'
	})
	.state('details', {
		url: "/details/:id",
		templateUrl: 'templates/details.html',
		controller: 'detailsCtrl'
	});
}])

PeopleService

Let’s set up a PeopleService via a factory with two methods. One, is the GetPeople method which gets all the people in an array and resolves a promise via $http before storing it in a private variable. The GetPerson method looks up a person by personId in that private variable.

.factory('PeopleService',['$http',function($http){
    var people = []; //Private Variable
    return {
        GetPeople: function(){ 
            return $http.get("path/to/resource").then(function(response){
                people = response;
                return response;
            });
        },
        GetPerson: function(personId){
            for(i=0;i<people.length;i++){
                if(people[i].id == personId){
                    return people[i];
                }
            }
        }
    }
}]);

We’ll assume the GetPeople method will return a data structure like the following:

var response = [
	{id: 1, firstName: "Andrew", lastName: "McGivery", bio: "Everything is awesome." },
	//... etc
]

Controllers

In our masterCtrl we will want to call that GetPeople function and set the result (the people array) to the $scope so it can be found to the master list.

.controller("masterCtrl",['PeopleService',function(PeopleService){
    PeopleService.GetPeople().then(function(people){
        $scope.people = people;
    });
}]);

Finally, in our detailsCtrl, we will get the personId from the $stateParams and use it to call the GetPerson method from our service.

.controller("detailsCtrl",['$stateParams','PeopleService',function($stateParams,PeopleService){
    var personId = $stateParams.id;
    $scope.person = PeopleService.GetPerson(personId);
}]);

Conclusion

The master detail pattern is a very common pattern that you will most likely run into if you make any sort of app. Using the combination outlined above in ionic/angular will make this very simple.

More Reading

Ionic: Using Factories and Web Services for Dynamic Data
Structure of an Ionic App
Creating Views with Ionic
Original Question/Answer on Stack Overflow

My name is Andrew McGivery. I currently work full time as an application developer at Manulife Financial in Canada. My current passion is building and leading highly engaged teams where employee happiness, learning, and growth is a priority.

25 Responses

  1. cfjedimaster

    One small nit – if the person hits the detail page first, won’t it throw an error since the people list wasn’t loaded?

    • andrewmcgivery

      Correct. This code assumes a typical mater detail pattern where you typically won’t be able to hit the detail page without first hitting the master page.

  2. […] Views with Ionic Ionic: Using Factories and Web Services for Dynamic Data Ionic: Master Detail Pattern “Models” and “Collections” in Ionic and […]

  3. spidermarket

    Don’t know if this is the right place to ask, but here goes.

    Suppose I want to add a page (view) that has the swipeable card.

    How do I implement this to my sidemenu?

    I’ve tried several times, but my page (view) gets all blacked out when I navigate to it.

    If you’re not sure what I mean, you can look at this q that I posted on stackoverflow, still haven’t gotten a replied yet.
    http://stackoverflow.com/questions/26514639/how-do-i-combine-views-ui

    Any suggestions would be appreciative.

  4. Hi, I have a problem, I’m consuming a json and at first view everything looks fine, but when the data passed to the second view data does not appear. I show my code:
    http://forum.ionicframework.com/t/data-no-share-between-views/13115

  5. Hi Andrew. Nice article. Would you be so kind to provide an example using ion-nav-view for history navigation?

  6. Hi. Do you have a codepen example with this?!

    thanks in advance and good article.

  7. I need a bit of help here. I have am Master Detail View Application with a Login ViewController in the Front of it.

    Now I have to add some stuff to my Detail View Controller which forces me to add a side menu to it. Now I found a lot of tutorials to add a side menu.

    The Problem I have is that the tutorial is only for a Viewcontroller not for a Master/Detail View Controller.

    And so far I didnt found anything regarding Master/Detail and side menu.

    Maybe you guys can help.

  8. I need a bit of help here. I have am Master Detail View Application with a Login ViewController in the Front of it.

    Now I have to add some stuff to my Detail View Controller which forces me to add a side menu to it. Now I found a lot of tutorials to add a side menu.

    And so far I didnt found anything regarding Master/Detail and side menu.

    Maybe you guys can help.

  9. I need help ! somehow my Detail View only returns id! Ive posted my question here : http://stackoverflow.com/questions/30164634/ionic-master-detail-returns-only-id

  10. sithot28

    Good article!,
    Andrew, I have problem with master detail. I have code just like your code above, except, when call detail view, before $http.get I call $cookieStore.get(‘starter.user’) to get user login status. My code running well on ionic serve environment, but not run in android devices. Any clue to solve my problem ?

  11. Derek Hannah

    what if you need to make a second $http call to get the detail that matches the stateParams.id?

  12. SerenityRH34

    HI.. I got an error problem please see –> http://stackoverflow.com/questions/32851972/how-to-call-data-on-ionic-with-api thank you.. 😉

  13. SerenityRH34

    where will I put my factory??.. console does not read it

  14. Hi Andrew, nice tutorial. Is there a preferred alternative mechanism to var personId = $stateParams.id; What if we don’t want to have the id on the URL? Also how to prevent invalid ids being entered manually? (that is, if I input an invalid id it goes back to the master page?).

    • So, couple things. We’re assuming a mobile app here in which case the user won’t be seeing URLs and can’t change the URLs. It is possible to pass the id in other ways, but this is much easier at the moment.

      In Ionic 2, it will be super simple to pass data between views without using the URL.

  15. while am passing an id to the master.html its redirecting to my login page

Leave a Reply