Tutorial hero
Lesson icon

2 Ways to Make Your Sencha Touch Models Smarter

Originally published May 02, 2014 Time 5 mins

A typical model definition for a Sencha Touch developer might look something along the lines of this:

Ext.define('MyApp.model.MyModel', {
  extend: 'Ext.data.Model',
  requires: ['Ext.data.identifier.Uuid'],
  config: {
    identifier: {
      type: 'uuid',
    },
    fields: [
      { name: 'name', type: 'string' },
      { name: 'picture', type: 'string', mapping: 'picture.data.url' },
    ],
  },
});

Most people, beginners especially, will be unlikely to use anything outside of the name and type properties. That’s the beauty of it though I think, models can be as easy or as complex as they need to be. In most cases a simple model definition like this will work perfectly. But sometimes we have to deal with funny data that doesn’t play nicely with our model, and Sencha Touch provides ways to deal with this. I’m going to be talking about two things in particular that I’ve found to be extremely useful, that you may not have come across just yet.

Mapping data in models

Here’s a good example. When I access a users friends list through the Facebook API I get sent back a bunch of data in an object that looks like this:

Data returned from Facebook API

Data returned from the Facebook API

The birthday, id and name fields are returned in an easy to work with way. Great. Everything looks perfect until you take a look at the picture data, this is returned as another object itself – that’s annoying. When I set this data on my model I want the picture field to be the URL to the image, not an object. Understandably, Facebook has added an easy way to programatically check if the user has a picture set or not but it makes out job a whole lot harder. Or so it would seem.

This is where the ‘mapping’ property comes in to save the day. If I add mapping to the field definition, I can circumvent this problem completely:

{name: 'picture', type: 'string', mapping: 'picture.data.url'},

If we were to assign the url of this object to a variable we would do this:

var url = picture.data.url;

So this is exactly what we set the mapping as. Now when we add the data from Facebook, Sencha Touch will drill down into that object to find the URL property assigned through the mapping and set that instead.

Manipulating data with the convert function

Sencha Touch models can get fancier still though with the convert functions, this can also come in very handy. I’m going to refer to another Facebook example, this time we’re going to look at some troublesome data formatting.

You will have noticed in the object returned above that I was able to retrieve the friends birth date. This would be a lot easier if everybody’s birthdays were returned in the same format, however on Facebook there are three distinct privacy permissions that can affect the visibility of birthdays:

  • Do not display birth date
  • Display day and month only
  • Display full birth date

Which means I could receive any of the following data back from Facebook

  • null
  • mm/dd
  • mm/dd/yyyy

Not only am I receiving different types of data, but that is not the format I want to display it in either. Fortunately, the convert function can solve all these problems for me. With the convert function we can pass in the value, do any kinds of tests or conversions we want on it, and then return the new value we would like to use. Here’s a simplified example of how you can set it up:

{
     convert: function(value, rec){
          //do something
          return value;
     },
     name: 'birthday', type: 'string'
},

In my case, I performed a test for each of the possible cases with the following results:

  • If the value is null, return “Private”
  • If the value is mm/dd, return in the format of “May 2”
  • If the value is mm/dd/yyyy, return in the format of “May 2 ‘14′”

and here’s exactly how I did it:

{
	convert: function(value, rec){

		//Check if the user is displaying their birthday
		if(value == null) {
			return 'Private';
		}
		//Check if the user is only displaying month and day
		else if(value.length == 5) {

			//Format the date
			var month_names = new Array("January", "February", "March",
				"April", "May", "June", "July", "August", "September",
				"October", "November", "December");

			var split = value.split("/");
			var date = new Date('1970', split[0] - 1, split[1]);
			var month = date.getMonth();
			var formatted_date = month_names[month] + " " + date.getDate();

			return formatted_date;
		}
		else if(value.length ==10) {

			//Format the date
			var month_names = new Array("January", "February", "March",
				"April", "May", "June", "July", "August", "September",
				"October", "November", "December");

			var split = value.split("/");
			var date = new Date(split[2], split[0] - 1, split[1]);
			var month = date.getMonth();
			var formatted_date = month_names[month] + " " + date.getDate() + " '" + date.getYear();

			return formatted_date;
		}
		else{
			return 'Private';
		}
	},
	name: 'birthday', type: 'string'
},

I’ve done an awful lot of talking about Facebook in this post, if you’re developing with the Facebook API I have another blog post on the topic here, and my eBook also provides an in-depth tutorial on integrating Facebook with Sencha Touch.

Learn to build modern Angular apps with my course