Tutorial 6 How to create a list

What you will learn in this Tutorial

How to Create list and fetch data from local device database

How to Create list and fetch data from remote data source

Download Source Code - Tutorials - Source for this tutorial is in appemble-tutorial-list
Learn more FAQ

Good Read

Tutorial - How to navigate from a list item

Tutorial - How to create a searchable list

Tutorial - How to create a section list

Reference LIST control

Introduction

In this tutorial you will learn how to create a simple list. A LIST control allows you to display a list of items. If the number of items exceed the height of the mobile device screen, then the list control provides the scroll bar automatically.

The data for the list control can be populated from a local database residing on your device or it can be fetched using a URL. In case the data is fetched from a remote URL it is first stored in the local data so that the list control can scroll smoothly.

  Local Remote
Android ../_images/simplelist.png ../_images/remote-list.png
iOS ../_images/ios_simplelist.png ../_images/ios_remotelist.png

Fig 1.

Note

The source code for this tutorial is in appemble-tutorial-list

Create list and fetch data from local device database

What is a LIST Control? It is a group control which has one or more child controls. In the Fig 1., you can see a list displaying a grocery item and the category of the item as one row of the list. Grocery item and its Category are the two child controls of the LIST Control. You can set the background of a list by specifying a color or an image. To get the data for the list from local database, the attribute local_data_source is used for the LIST control. local_data_source takes a sql query to display the data.

To understand more, create a list tutorial project. Create list.xml

<screens>
    <screen name="list" screen_type="SCREEN" menuOrder="0" menuName="Local List"
    initial_layout="PORTRAIT" allowed_layouts="BOTH" width="100" height="100"
    tab_group_name="tabgroup1">
        <title_controls>
            <control type="TEXT" x="0" y="1" width="100" height="6"
                default_value="My Shopping List - local datasource" appearance_name="white"/>
        </title_controls>

        <controls>
            <control type="LIST" x="0" y="0" width="100" height="100"
                appearance_name="black" data_type="VARCHAR"
                local_data_source="select list_item_id as _id, item, category
                from myshopping_list order by category"
                on_empty_show="show_when_list_is_empty" >
            <!-- Child controls of list -->
                <control type="TEXT" x="3" y="2" width="27" height="7"
                    appearance_name="black" data_type="VARCHAR" field_name="item" />
                <control type="TEXT" x="35" y="2" width="50" height="7"
                    appearance_name="black" data_type="VARCHAR" field_name="category" />
                </control>
            <control name="show_when_list_is_empty" type="TEXT" x="3" y="2" width="60"
                height="7" permission="READONLY" appearance_name="black"
                default_value="Your list is empty"/>
       </controls>
    </screen>
</screens>

The data to be displayed in the list is retrieved from local database which is in your-project /assets/ your-project-content.sqlite.

For this example create a table myshoppinglist in the content database (your-project-content.sqlite)

CREATE TABLE [myshopping_list] (
  [list_item_id] INT,
  [item] VARCHAR(80),
  [category] VARCHAR(80));

Enter the data to be displayed in the list.

Note

  • The data is retrieved from the table myshopping_list using a select query. The query is executed on the content database is defined in the your-project/res/strings.xml.
  • In order to bind the data to an intended child control, the column name of the query result set must be the same as the field_name of the control. Underlying AVM will bind a column of the result set to the child control by comparing the field_name with the column name.
  • If the column names differ from the field name, you can modify the query as select col1 as field_name1, col2 as field_name2 from table t. Though it is a good practice to keep the field_name same as the column_name of the data source
  • If there is a mismatch between the column names of the result set and the field_name, the data will not be displayed correctly and you could see empty list.
  • If the list is empty, all controls that are listed in the attribute “on_empty_show” in the list will become visible.

To define different appearances, create a new file or edit a file called appearance.xml in the app-def folder:

<appearances>
    <appearance name="black_bold" font_family="Sans-Serif"
            font_name="Helvetica" font_size="3"
            font_color="#000000" background_color="#FFFFFF" alpha="0"
            justify="LEFT" font_style_bold="1"/>
    <appearance name="black" font_family="Sans-Serif"
            font_name="Helvetica" font_size="3"
            font_color="#000000" background_color="#FFFFFF" alpha="0"
            justify="LEFT" />
    <appearance name="white_bold" font_family="Sans-Serif"
            font_name="Helvetica" font_size="3"
            font_color="#FFFFFF" background_color="#FFFFFF" alpha="0"
            justify="LEFT" font_style_bold="1"/>
    <appearance name="white" font_family="Sans-Serif"
            font_name="Helvetica" font_size="3"
            font_color="#FFFFFF" background_color="#000000" alpha="0"
            justify="CENTER" font_style_bold="1"
            font_style_emboss="1"/>
    <appearance name="white_left" font_family="Sans-Serif"
            font_name="Helvetica" font_size="3"
            font_color="#FFFFFF" background_color="#000000" alpha="0"
            justify="LEFT" font_style_bold="1"
            font_style_emboss="1"/>
    <appearance name="edit_box" font_family="Sans-Serif"
            font_name="Helvetica" font_size="3"
            font_color="#000000" background_color="#FFFFFF" alpha="255"
            justify="LEFT" />
    <appearance name="grey_bkgrnd" font_family="Sans-Serif"
            font_name="Helvetica" font_size="3"
            font_color="#DDDDDD" background_color="#DDDDDD" alpha="255"
            justify="LEFT" />
    <appearance name="blue_bkgrnd" font_family="Sans-Serif"
            font_name="Helvetica" font_size="3"
            font_color="#000000" background_color="#3399CC" alpha="255"
            justify="LEFT" />
    <appearance name="grey_button" font_family="Sans-Serif"
            font_name="Helvetica" font_size="2.7"
            font_color="#000000" background_color="#FFFFFF" alpha="255"
            justify="CENTER" />
</appearances>

Now declare that list screen is the first screen to be displayed. This is declared in a file in your app-def folder called application.xml

<screen_deck name="list_tutorial" version="1.0"
        short_description="List Tutorial app"
        long_description="List Tutorial app" size="1024"
        publisher_name="Appemble"
        publish_date="2012-09-27" starting_screen_name="list"
        background="tu_background.png"
        title_background="tu_titlebar.png"/>

Test your app.

Android - Right click on the project and click on Run as Android application.

iOS - Click on Product -> Run.

Create list and fetch data from remote data source

There are 2 ways in which remote data can be fetched.

  1. Define attribute(s) remote_data_source=<your URL>, remote_data_format=”JSON” remote_data_save_locally=”true”, update_screen=”true” for the element <screen>. This will fetch the remote data and make an attempt to save it in the local database. Define the attribute data_type="CURSOR" for LIST control. AVM will then populate the list box from the data fetched from the local database.

The data flow is remote -> local -> LIST control. This is the default option for displaying data from remote data source. In this tutorial, this option has been used.

  1. Define attribute(s) remote_data_source=<your URL>, remote_data_format=”JSON” remote_data_save_locally=”false”, update_screen=”true” for the element <screen>. This will fetch the remote data. The JSON data fetched will be saved into memory using JSONArray. This JSONArray will then be directly sent to the control. data_type="JSONARRAY" for LIST control. Data flow is remote data -> LIST control

Create remotelist.xml Remote data has been made available from "http://swimdash.com/swimdash/index/index/category/3/format/json"

<screens>
    <screen name="remotelist" screen_type="SCREEN" menuOrder="1" menuName="Remote"
            initial_layout="PORTRAIT" allowed_layouts="BOTH"
            width="100" height="100" tab_group_name="tabgroup1"
            remote_data_source="http://swimdash.com/swimdash/index/index/category/3/format/json"
            remote_request_type="GET">

        <title_controls>
            <control type="TEXT" x="0" y="1" width="100" height="6"
                    default_value="Swim meets - remote datasource"
                    appearance_name="white" data_type="VARCHAR"/>
            <control type="PROGRESSBAR" x="91" y="2" width="5.7"
                    height="3.6" permission="READONLY"
                    appearance_name="black" data_type="VARCHAR"
                    default_value="IMAGE:progressbar4.gif" />
        </title_controls>
        <controls>
            <control name="remotelist" type="LIST" x="0" y="0" width="100"
                    height="100" permission="READONLY"
                    appearance_name="black" data_type="CURSOR"
                    local_data_source="SELECT sdid as _id, sdid, title, logo,
                (substr(start_date, 7,4) || '-' || substr(start_date, 1,2) || '-' ||
                substr(start_date, 4,2) ) as start_date, (substr(end_date, 7,4)
                || '-' || substr(end_date, 1,2) || '-' ||  substr(end_date, 4,2) )
                as end_date, meet_class  FROM featured order by start_date desc">

                <!-- Child controls of list -->
                <control type="IMAGE" x="1" y="1" width="12"
                        height="10" permission="READONLY"
                        appearance_name="black" data_type="VARCHAR"
                        field_name="logo" size="255"  />
                <control type="TEXT" x="20" y="1" width="60"
                        height="7" permission="READONLY"
                        appearance_name="black" data_type="VARCHAR"
                        field_name="title" size="255" />
                <control type="TEXT" x="20" y="8" width="35"
                        height="7" permission="READONLY"
                        appearance_name="black" data_type="DATE"
                        format_type="EEE,MMM d,yyyy" field_name="start_date"
                        size="255" storage_format="yyyy-MM-dd" />
                <control type="TEXT" x="57" y="8" width="5" height="7"
                        appearance_name="black" data_type="VARCHAR"
                        default_value="to" />
                <control type="TEXT" x="20" y="15" width="35" height="7"
                        appearance_name="black" data_type="DATE"
                        format_type="EEE,MMM d,yyyy" field_name="end_date" size="255"
                        storage_format="yyyy-MM-dd" />
                <control type="TEXT" x="0" y="0" width="0" height="0"
                        appearance_name="black" data_type="VARCHAR"
                        field_name="meet_class" size="40" />
                <control type="TEXT" x="0" y="0" width="0" height="0"
                        appearance_name="black" data_type="INT" field_name="sdid"  />
            </control>
        </controls>
    </screen>
</screens>

Now your app is ready for launch.

Android - Right click on the project and click on Run as Android application.

iOS - Click on Product -> Run.

Download and Run Tutorials

This chapter uses source code from appemble-tutorial-list. If you have not downloaded tutorial source code, click on Download Source Code - Tutorials

Android - Right click on appemble-tutorial-list and click on Run as Android application.

iOS - Select scheme appemble-tutorial-list and iPhone x.x simulator. Click on Product -> Run.

FAQ

How to fetch data from a remote server?

Many times data needs to be retrieved from a remote URL. This can be done by specifying a URL in the attribute “remote_data_source”. The URL will be executed in a background thread so that the application does not feel sticky.

How to store incoming data in the local database?

The URL response can be either parsed by the framework if it conforms to JSON and follows a certain structure. Alternatively you can write a custom function to parse the response and save it into the local database. The list box is must more efficient if its data is sourced from a database table residing on your local device especially with larger data size, it is a good practice to first store the remote data in the local database and then display it on the list box.

How can the framework parse the URL response?

If the server response follows these rules then the framework can save the URL response automatically.

  • URL response is in a JSON format
  • The response contains one or more JSON objects.
  • The name of the JSON object is same as the name of the table in the content database
  • The members of the JSON object has the key named after the column name of the content table.

In this example, a table “featured” has been created in the local content database - list-tutorial-content.sqlite. The URL specified in the remote data source is http://swimdash.com/swimdash/index/index/category/3/format/json. (You can execute this URL in the browser to see the response.) The response contains a JSON object called featured. This object name matches a table called “featured” in the local database. The JSON object contains an array of following elements

featured

../_images/featuredcode.png

Each element in the array “featured” contains 1 or more keys (for ex. title, start_date, etc). Each key has a corresponding column in the “featured” table.

Note

  • There is no limitation on the number of JSON objects received in the URL response.
  • If the JSON object is an array, then each element of the array will be saved as one row in the content table.

How to display the data in the list box?

Specify the local_data_source for the list box and the query will feed the data to the list box. You can choose the sorting order of the data in the query itself.

How to display a message on the screen when the list is empty?

In the list define the attribute on_empty_show=”name of control(s) comma separated”. In the screen (or at the same level as the list control), define controls that show the message. It could be just a text control that has a default_value to show the message or a combination of other controls.

How to write custom function to parse the URL response?

Appemble Framework supports json response format and it can save the data into local content tables if the response structure matches the database schema. If the response structure is different, a parsing function can be written to read and write to the local database.

Can I put any type of child control in the list?

You can put TEXT, IMAGE, SINGLE_CHOICE_DIALOG, SINGLE_CHOICE_PICKER controls. See Child controls of LIST