Sencha Inc. | HTML5 Apps

Blog

Dive into DataView with Sencha Touch 2 Beta 2

February 08, 2012 | Robert Dougan

Today we’re releasing Sencha Touch 2 beta 2, which contains around 100 enhancements, examples, and bug fixes based on your feedback from last week’s beta 1. We’ve been really energized by all your positive feedback on beta 1 and would like to reiterate our appreciation for the time and energy you put in to creating apps, reporting bugs and sharing your experiences with others.

Beta 2 should be a drop-in replacement for beta 1, and as before, we have prepared a full set of release notes. We hope you’ll continue to let us know what you think of the release in the comments, twitter and your own blogs.

Download Sencha Touch 2 Beta   View Release Notes

UPDATE: Sencha Touch 2 RC is now available. Go download that instead!

Great Progress on ICS Issues

Last week we asked for your help in raising awareness of a critical performance issue with Android 4/Ice Cream Sandwich. Thanks to your participation the bug report has been starred over 250 times and last week yielded a patch from the Android team that addresses the flashing that can happen before animations.

While that’s great news, it’s only half the story so we’d like to ask for your help one more time. While the flashing is gone, we feel that Android 4 is still not performing as well as it should when it comes to animations so if you’re in favor of better animation performance on Android 4, we’d like to ask you to take a moment to click the star on this bug report to let the Android team know how much this matters to everyone building HTML5 applications.

DataView Improvements

DataView is a powerful Component that enables you to render an HTML template for each record in a Store. While that’s very useful, Sencha Touch 2 raises the bar by allowing you to render entire Components for each record. This enables a wealth of new UI options and we’d like to take the rest of this post to walk you through what’s improved.

Component DataView

The Sencha Touch 2 DataView offers two ways to render items from a Store: element based and component based. In 1.x only the element-based approach was available, which made it difficult to do things like add a Button to each item in a List.

Turning your element-based DataView into a component-based one is straightforward. With a template based DataView, you normally specify a store and itemTpl configuration, but with a component based DataView, you do not need to specify an itemTpl. Instead, you set the useComponents configuration to true. This tells DataView that it will be rendering components.

Next we have to tell it which types of components it will be rendering. To do this, we set a defaultType for our DataView. This tells the DataView which type of Component to create for each record.

In the example below, we’re creating a fullscreen component-based DataView that uses the kittenslistitem type to create each item (we’ll create this kittenslistitem Component in a moment). We’re also passing in a Store full of kittens. DataView will render one kittenslistitem for each kitten:

Ext.create('Ext.DataView', {
    fullscreen: true,
    useComponents: true,
    defaultType: 'kittenslistitem',
    store: {
        fields: [
            "name",
            "image",
            { name: "cuteness", type: 'int' }
        ],
        data: [
           { name: 'Yawning kitten', image: 'data/images/kitten1.jpg', cuteness: 70 },
           { name: 'Sitting kitten', image: 'data/images/kitten2.jpg', cuteness: 90 },
           { name: 'Evil kitten', image: 'data/images/kitten3.jpg', cuteness: 70 },
           { name: 'Ginger kitten', image: 'data/images/kitten4.jpg', cuteness: 80 },
           { name: 'Kitten friends', image: 'data/images/kitten5.jpg', cuteness: 20 },
           { name: 'Milk kitten', image: 'data/images/kitten6.jpg', cuteness: 50 }
        ]
    }
});

Custom DataView Item

Now we have a component DataView and we’ve told it to use a component with an xtype of kittenslistitem. That hasn’t been defined yet; so let’s do that now.

It is important to note that this DataView item must extend Ext.dataview.component.DataItem. This is because this object includes important functionality to bind a specified record to the component.

Our custom DataView item will include three items:

Wireframe of our custom DataView item
Wireframe of our custom DataView item

Each of these components will be defined as a configuration in our KittenListItem class. Once the class is instantiated for each record, the configurations will be added into the item. This looks like the following:

Ext.define('KittensListItem', {
    extend: 'Ext.dataview.component.DataItem',
    xtype: 'kittenslistitem',
 
    config: {
        image: true,
 
        name: {
            cls: 'x-name',
            flex: 1
        },
 
        slider: {
            flex: 2
        },
 
        layout: {
            type: 'hbox',
            align: 'center'
        }
    }
});

Let’s start from the top:

  • Define the KittensListItem which we will use in our component DataView
  • Extend Ext.dataview.component.DataItem
  • Inside the config object, add a new config called image and set it to true (this will be transformed into a Ext.Img component)
  • Create another config called name. This is an object containing a cls and a flex property of 1 (this will be transformed into an Ext.Component component)
  • Create another config called slider which has a default flex of 2 (this will be transformed into a Ext.slider.Slider)
  • And finally give it a HBox layout and vertically align the items in the center.

For each new configuration we create, we need to create the appropriate apply and update methods so they get transformed into the correct component, and inserted into this item. Lets do this for the image configuration:

 applyImage: function(config) {
     return Ext.factory(config, Ext.Img, this.getImage());
 },
 
  updateImage: function(newImage, oldImage) {
     if (newImage) {
         this.add(newImage);
     }
 
     if (oldImage) {
         this.remove(oldImage);
     }
 }

First, we define the applyImage which is called when this component is initialized and each time the image configuration is changed. In the method, we use Ext.factory to transform the configuration into a Ext.Img component. We then define the updateImage method which is called after applyImage. This method gets called with two arguments: the new image, and the old image (if one existed before). In this method we simply check if newImage exists and add it to this component Data Item, and the same for the oldImage, except in this case we’re removing it.

We then repeat this process for the other two configurations: name and slider.

If you want to learn more about how the Class System works, there is a great guide written by Jacky Nguyen in the Sencha Touch 2 Documentation.

Mapping the Record to the DataItem

Now we have the component data item created which will be used in our DataView. The three new configurations we created are automatically transformed into components and added into the item. The next step is configuring the map between the record and the item displayed in the list. Remember we have three fields we need to map:

  • name -> html config of the name component
  • image -> src config of the image component
  • cuteness -> value config of the slider component

To do this, we use the dataMap configuration in our DataItem. This configuration allows us to map a setter of a configuration in our DataItem to a field in the record bound to our DataItem. Lets look at an example:

config: {
    …
 
    dataMap: {
        getImage: {
            setSrc: 'image'
        }
    }
}

Once this DataItem is added into DataView and the record is updated, this will essentially do this:

this.getImage().setSrc(record.get('image'));

As you can see, it is using the getter for our new image config, then calling the src setter on the Ext.Img component with the image field of our record.

We now repeat this process for the name and cuteness fields, so the appropriate components are updated. And the final dataMap is:

config: {
    …
 
    dataMap: {
        getImage: {
            setSrc: 'image'
        },
        getName: {
            setHtml: 'name'
        },
        getSlider: {
            setValue: 'cuteness'
        }
    }
}

Now that the DataItem is mapped to the record, we can load up our example in a browser. And when we add some CSS sparkle, the demo will look a little like this:

KittensListItem
View the ultra-cute kittens DataView example

Conclusion

You can view a live demo of this example on Sencha Labs and the full source code (with lots of comments!) over on GitHub.

The enhanced DataView in Sencha Touch 2 Beta 2 makes it easy to build complex data bound lists. If you have issues or find bugs with the beta, feel free to drop by our forums and let us know. We’re actively hunting down and fixing bugs, so let us know if there are things you’re expecting to work that just aren’t.

There are 15 responses. Add yours.

John

3 years ago

You guys never cease to amaze me… I know everyone really appreciates the hard work, thank you!

Bruce Sklar

3 years ago

I’ll second John’s vote, you guys are amazing.  I appreciate all the hard work, thank you!

Eugene

3 years ago

Pretty impressive.

BC

3 years ago

Great stuffs! Knocking the bottom out of it for sure.

LoreZyra

3 years ago

looks like you guys have a typo in the source code for KittensListItem. There’s a end paragraph tag in the code that I suspect should not be there…

Ext.define('KittensListItem'{
    extend
'Ext.dataview.component.DataItem',
    
xtype'kittenslistitem',</p

AndyD

3 years ago

So… is there a list somewhere of all magical words that change into components (ie: slider, image and name)...

AndyD

3 years ago

Scratch my previous remark, I obviously didn’t read it very well.

Michael Mullany Sencha Employee

3 years ago

@lorezyra. Thanks for catching the - this looks like a bug in Expression Engine, it’s not in our blog text! We’ll track it down.

Jay Robinson Sencha Employee

3 years ago

LoreZyra, fixed. Sorry about that.

Umair Ashraf

3 years ago

What about if the setters needs to have concatenated value like…setHtml: ‘name’ + ’ constant’?

Robert Dougan Sencha Employee

3 years ago

@Umair Ashraf

For more advanced behavior like that, we advice you to override the updateRecord method in your dataItem. This method will get two arguments: newRecord and oldRecord. With this data, you can then do whatever you need in your dataItem. Just make sure you callParent(arguments). smile

Loiane

3 years ago

So nice!
Btw, love the example, so cute! wink

J. Austin

3 years ago

Looks good Robert,
  Do you have any advice on how to add a Button or any other component that isn’t directly tied to a field on the model ?

Michael

3 years ago

I added a checkbox on each row successfully but I cannot have itemtap event any more because itemtap is triggered when user clicks on checkbox.

Any suggestions?! Thank you!

Lawrence

3 years ago

Looks good. But how, for example if I would like to add the same component in the list.
Say for example two buttons inside the item list.

How to implement this?
Thanks you!

Comments are Gravatar enabled. Your email address will not be shown.

Commenting is not available in this channel entry.