Question

I'm migrating from a TableView to a ListView in Titanium. One of the new requirements it that the list is grouped alphabetically into ListSections. I can think of a way that I can do this using just Javascript, by generating the ListView data and then outputting each one as an alphabetical group in a ListSection.

However, I'm trying to find a way to do this using Titanium Alloy with Data Binding and I can't find any examples online, even in the Titanium Kitchen Sink.

Here is what I have so far, I can get the data output in one ListSection:

    <ListView id="brandList">

        <Templates>
            <ItemTemplate name="template" id="template">
                <View>
                   <ImageView bindId="image" class="programmeImage" />
                   <Label bindId="name" class="programmeTitle" />
                   <ImageView bindId="channel" class="channelBrand" />
                </View>
            </ItemTemplate>
        </Templates>

        <ListSection dataCollection="brands">
            <ListItem template="template" name:text="{name}" image:image="{cached_image}" channel:image="{channel}" />
        </ListSection>

    </ListView>

This outputs the list just fine and the data binding works great, but I have no idea of how to make a list section for each alphabetical group, as in the example image below. It this even possible using Alloy?

Example:

enter image description here

Was it helpful?

Solution

You can use Alloy for this, but you have to use create the sections and index in your controller.

views/index.xml

Define the list view and its templates in the XML. We're not doing data binding here because we need to define sections in the controller.

<Alloy>
<Window>
    <ListView id="list" defaultItemTemplate="title">
        <Templates>
            <ItemTemplate name="title" height="50">
                <Label bindId="title" class="title"/>
            </ItemTemplate>
        </Templates>
    </ListView>
</Window>
</Alloy>

models/info.js

You'll need a model to define your storage structure. You could leave off the id column and idAttribute -- I just grabbed some existing code that had those and didn't bother testing without them. I'm extending the collection with a method that will sort the collection automatically on fetch().

exports.definition = {
config: {
    columns: {
        id: 'INTEGER PRIMARY KEY AUTOINCREMENT',
        title: 'TEXT'
    },
    adapter: {
        type: 'sql',
        collection_name: 'info',
        idAttribute: 'id'
    }
},
extendCollection: function(Collection) {
    _.extend(Collection.prototype, {
        // Implement the comparator method,
        // which is used to sort the collection
        comparator : function(name) {
            return name.get('title');
        }

    }); // end extend

    return Collection;
}
};

controllers/index.js

Here's how I created the functionality. I loop through an array of letters, which will be my index, creating the section for each letter if there are names that begin with that letter

var info = Alloy.createCollection('info');
info.fetch();

var sections = [];
var sectionIndexArray = [];
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' ];
_.each(letters, function(letter) {
    var data = info.filter(function(name) {
        var n = name.get('title');
        if(n.charAt(0).toLowerCase() === letter) {
            return name;
        }
    });
    if(data && data.length >0 ) {
        var section = Ti.UI.createListSection();
        var items = _.map(data, function(item) {
            return { title: {text: item.get('title')}};
        });

        section.setItems(items);
        sections.push(section);
        sectionIndexArray.push({index: (sections.length -1 ), title:     letter.toUpperCase() });
    }
});

$.list.sections = sections;
$.list.sectionIndexTitles = sectionIndexArray;

$.index.open();

Finally, you need to populate your collection. For my testing, I added the following to my alloy.js file. It could have been in the index.js.

var firstLadies = [
    "Adams, Abigail",
    "Adams, Louisa Catherine",
    "Arthur, Ellen Herndon",
    "Bush, Barbara",
    "Bush, Laura",
    "Carter, Rosalynn",
    "Cleveland, Frances Folsom",
    "Clinton, Hillary Rodham",
    "Coolidge, Grace Goodhue",
    "Eisenhower, Mamie Doud",
    "Fillmore, Abigail Powers",
    "Ford, Betty",
    "Garfield, Lucretia Rudolph",
    "Grant, Julia Dent",
    "Harding, Florence Kling",
    "Harrison, Anna Tuthill Symmes",
    "Harrison, Caroline Lavinia Scott",
    "Harrison, Mary Lord",
    "Hayes, Lucy Webb",
    "Hoover, Lou Henry",
    "Jackson, Rachel",
    "Johnson, Eliza McCardle",
    "Johnson, Lady Bird",
    "Kennedy, Jacqueline",
    "Lincoln, Mary Todd",
    "Madison, Dolley",
    "McKinley, Ida Saxton",
    "Nixon, Pat",
    "Obama, Michelle",
    "Pierce, Jane Means",
    "Polk, Sarah Childress",
    "Reagan, Nancy",
    "Roosevelt, Edith Kermit Carow",
    "Roosevelt, Eleanor",
    "Taft, Helen Herron",
    "Truman, Bess Wallace",
    "Van Buren, Hannah Hoes",
    "Washington, Martha",
    "Wilson, Edith Bolling Galt",
    "Wilson, Ellen Axson"
];

if (!Ti.App.Properties.hasProperty('seeded')) {
    for(var i=0,j=firstLadies.length;i<j;i++) {
        Alloy.createModel('info', { title: firstLadies[i]}).save();
    }
    Ti.App.Properties.setString('seeded', 'yes');
}

finished app

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top