If you follow me on Twitter, you know I've been raving about Ionic the past few weeks. I've played around with it a bit but haven't yet built a proper "sample" app. I still plan on doing so sometime soon. Today though I wanted to share a little experiment I built last night.
One of the directives that ships with Ionic is the ability to build nicely formatted lists. If you create a sample Ionic application based on the Tabs starter application, you can see a nice example of this.
I won't share all the code behind this as you can see it for yourself if you create a new application based on the Tabs app (ionic start somename tabs
), but here is the view used to render that screen shot. Note that the data comes from a service (with static values) and everything is set up by an Angular controller.
<ion-view title="Friends">
<ion-content class="has-header">
<ion-list>
<ion-item ng-repeat="friend in friends" type="item-text-wrap" href="#/tab/friend/{{friend.id}}">
{{friend.name}}
</ion-item>
</ion-list>
</ion-content>
</ion-view>
Nice and simple, right? This is why I'm really digging Angular lately. While this works, one of the issues you run into is performance if your list is large. Of course, "large" is relative. But if you were to go from a list of a few friends to a few thousand, you will see performance degrade due to the size of the DOM being rendered.
Turns out - the devs at Ionic have a solution for it. By making use of collectionRepeat, you get an updated list directive that smartly handles large lists. It can dynamically add to and remove from the DOM based on what is actually visible and has much better performance for larger lists.
It isn't just a simple code change. If you read the docs for it you will note some things you have to take care of versus the simpler list control, but it isn't that difficult. I modified one of the tabs to make use of it like so:
<ion-view title="Account">
<ion-content class="has-header">
<ion-list>
<ion-item collection-repeat="friend in friends"
collection-item-width="'100%'"
collection-item-height="80">
{{friend.name}}
</ion-item>
</ion-list>
</ion-content></ion-view>
I should point out - this is not an exact replacement. As you'll see in a second, the UI is different. I could have fixed that but I was just interested in seeing the actual performance difference. I went into the service file for the app and modified it to add a bit more data:
angular.module('starter.services', [])
/**
* A simple example service that returns some data.
*/
.factory('Friends', function() {
// Might use a resource here that returns a JSON array
// Some fake testing data
var friends = [
{ id: 0, name: 'Scruff McGruff' },
{ id: 1, name: 'G.I. Joe' },
{ id: 2, name: 'Miss Frizzle' },
{ id: 3, name: 'Ash Ketchum' }
];
//let's blow the shit out of this...
for(var i=0;i<20000;i++) {
friends.push({id:i+4, name:"Person "+i});
}
return {
all: function() {
return friends;
},
get: function(friendId) {
// Simple index lookup
return friends[friendId];
}
}
});
Not very realistic, but you get the idea. We've gone from 4 items to 2004. So what was the difference? Instance access to the list instead of about 5 seconds of waiting. See the video below for an example.
That's pretty significant if you ask me. For the heck of it, I tried 200K rows as well and it performed just as well. Speaking to one of the devs last night, the only real issue you have with this control is the amount of memory the actual data is holding, not the rendering.
In case you were wondering if Ionic is "just another UI" library, this is a great example of why it is so much more than that. Definitely check it out!