Skip to end of metadata
Go to start of metadata

Mission: In this lab, you will learn how TableViews and ListViews can both be used to display data to the user in a list. Then we will examine how the two perform differently when a large number of elements are shown.

SpecificationYou will be creating a friends list and a friends activity feed in the app. First you will use a TableView as you have done before. Then, the TableView will be replaced with a ListView and you will compare the performance of each implementation.

  1. First thing’s first: discuss use cases - TableView versus ListView
    1. TableView
      1. Easier to customize

      2. Can contain more complex views
      3. Slow, resource-consuming
    2. ListView
      1. Super fast
      2. Great for large amounts of similarly-formatted data
      3. Supports drastically fewer events, so there is less you can do with them
      4. Harder to work with
  2. ListViews have the same three-tiered hierarchy as a TableView
    1. TableView -> ListView
    2. TableViewSection -> ListSection
    3. TableViewRow -> ListItem
  3. ListViews are populated by creating an ItemTemplate which builds a ListItem’s UI the same way as you might a TableViewRow’s
    1. Key difference: Every UI element is provided a “bindId”
    2. “bindId” is a custom property that the ListView uses to reference that element while building the ListItems
      1. When building ListItems, bindId is associated with an object that can have properties assigned to it, like in TSS.
      2. Example:





      3. In the ListItem below the ItemTemplate, defaultLabel refers to the bindId for the Label in the ItemTemplate. Since labels have the “text” property, the line defaultLabel:text=’Hello world!” sets the text of that label to “Hello world!”

      4. By making it simple (I promise, it’s actually simple) to build great numbers of views while having easy access to their properties, ListViews make it easy to take a big array of data and turn it into a similarly-formatted list. Take the above example, but instead of creating a single ListItem with defaultLabel:text=’Hello World!’, you have a function written that iterates through an array of strings, setting each new ListItem’s defaultLabel’s text to the next string’s value. Hopefully now this is becoming clearer.
  4. Converting our TableView into a ListView
    1. Thankfully, due to the similarity of their structures, conversion is not difficult
    2. Download the starting code for this lab from this link and unzip the files. Import the project into Titanium Studio. Update the tiapp.xml, if necessary (e.g. to set an appropriate SDK version or build target for your environment).

    3. The TableView we’ve been using to input data to our chart will become the ItemTemplate for the ListView we create
    4. Step 1: Swapping the tags
      1. First thing’s first, change the TableView tag to ListView
      2. Wrap the entire block of the TableViewRow in Templates tags, and change “TableViewRow” to “ItemTemplate.”
        1. Give the ItemTemplate a name
        2. Assign this template to the ListView using the ListView’s defaultItemTemplate property
      3. Remove the hardcoded “1” from the rowId, as well as the + and - from the add and delete buttons.
      4. Assign a bindId to each one of these labels, views, textfields, and buttons. Name them whatever you’d like; I typically give bindId’s the same name as the regular id to avoid confusion
    5. Step 2: Building the rows
      1. In the onInitialLayout function, delete the dataObject initialization. We will instead be initializing the first ListItem here, and changing how our dataObjects get stored later.
        1. ListViewSections accept arrays of ListItem data objects, so create an object and wrap it in straight braces.
          1. Access the properties of each element by its bindId as mentioned in Step 3b
          2. Since we know the first rowId is 1, we can set it to that by accessing its text property through the bindId.
          3. Should end up looking a bit like building TSS, with each bindId being its own object to set properties on.





        2. The "properties" property

          1. This aspect of the ListItem object is important enough to receive it’s own tutorial section

          2. If the bindIds refer to the child objects of the ListItem, then the “properties” property refers to the ListItem itself.
            1. In other words, use the bindIds to style the individual elements of the ListItem, and use the “properties” property to style the ListItem as a wrapper for all of those elements.

            2. This is where you’d specify things like the background color, height, and width of each row of your ListView
        3. One difference between ListViews and TableViews is that with the latter, you can add TableViewRows directly to the TableView itself. With a ListView, you must add ListItems to a ListSection before they can be applied to the ListView

          1. Below the block of code where you created the ListItem’s data object, create a ListSection using Ti.UI.createListSection and pass the ListItem array to its “items” property

          2. Now using the ListView’s setSections() method, set this ListSection to the ListView. NOTE: setSections() also expects an array, so wrap your ListSection’s variable name in straight braces when passing it to the method

          3. And now we have our first ListView with a programmatically added row! Next up is the functionality to add and remove rows

    6. Step 3: Add & Delete row functions. Begin by completely deleting the contents of these functions.

      1. Add row:

        1. First, increment the rowIndex variable we’re maintaining to keep track of the new rows’ positions

        2. Next, create a data object for the new ListItem (you can reuse the one you used to initialize the ListView in Step 2)

          1. As an optional, purely aesthetic addition, I have used ternary operators to make every other row added this way alternate some colors in order to distinguish rows

          2. Feel free to skip this step if you’re pressed for time

        3. appendItems() is a method on ListSections and not ListViews, so you will want to access the ListSection with the ListView’s “section” property at index 0 (because we only have one ListSection).

          1. e.g.: $.listView.sections[0].appendItems()

          2. pass the appendItems() method the new ListItem you’ve built to add the item to the section, and thus the ListView

      2. Delete row

        1. Stringifying the event object on either of these click events will show you that ListItems and their children have an itemIndex property provided to them, which will make deleting rows very simple

          1. Set up an if-block to ensure that the itemIndex is greater than 0 (so that the user doesn’t delete the only ListItem), and within that block add the code for deleting a row

          2. Again, the deleteItemsAt() method is called on ListSections, so access them the same way as in the previous step.

          3. deleteItemsAt() however expects two arguments: the index to start deleting, and the number of items to delete. We’ll only ever be deleting one item at a time, so for our purposes, you can just make the second argument “1.” For the first argument, you can use evt.itemIndex to delete the row they clicked on.

        2. Don’t forget to decrement the rowIndex afterwards to keep the app up to date on the current index

    7. Step 4: Getting data from the ListView

      1. You cannot update properties of a ListView’s elements without entirely destroying and recreating them, so in order to get the data we want out of it, we’re going to do some javascript magic

        1. First we need to redo the dataObject initialization, but we’ll be doing it somewhat differently than before. Go to the top of index.js where dataObjects is declared, and set it equal to an empty array.

        2. Whenever we add a ListItem, push an empty object to the dataObjects array

          1. ListItems are added in onInitialLayout() and addRow()

          2. “pushing an empty object” is as simple as dataObjects.push({});

        3. Don’t forget to remove the corresponding dataObject if you delete a row

          1. You’ll want to use the array’s splice() method in the deleteRow function with the itemIndex

          2. It should look something like dataObjects.splice(evt.itemIndex, 1)

      2. Now in the index.xml add a listener to all of the TextFields for the ‘change’ event. All three should trigger the same function (I named mine “updateValue”)

        1. In this change function, create a switch for the event’s bindId

          1. make a case for “one,” “two,” and “three”: the three possible textfield bindIds

          2. for each case, set a custom property (I named mine after the bindIds to avoid confusion) equal to the event’s value on dataObjects specifying the event’s itemIndex as the dataObjects’ index.

          3. dataObjects should now be an up-to-date catalogue of each row’s textfield values that updates itself whenever the user types anything

        2. We can now use the dataObjects array to build our payload the same as before, but with one change. In buildPayload(), you can remove the “.value”s from the objects being pushed to valuesByColumn, as we are now directly storing that value

    8. Step 5: Build to the simulator and try out your newly completed ListView app

You can download the completed application from: this link
  • No labels