sencha-touchsencha-touch-2senchatouch-2.4

Displaying buttons in a Dataview in Sencha 2


I'm trying to create a view, which has essentially a list where each row has text and 2 buttons aligned right. The text of the buttons will always be the same - only the text of the row will need to be fetched from the store.

I saw this question but couldn't get the proposed solution to work. I definitely have records in my store, but the dataview does not display.

A simplified version of my code:

My main view:

Ext.define('MyApp.view.Main', {
    extend: 'Ext.Container',
    ...
    config: {
        layout: {
            type: 'vbox',
            pack: 'center',
            align: 'middle'
        },
        items: [
           ...
           {xtype: 'mylist'}
           ...
        ]
        ...
    }
    ...
});

DataView:

Ext.define('MyApp.view.MyList', {
    extend: 'Ext.dataview.DataView',
    alias: 'widget.mylist',
    requires: ...,
    config: {
         useComponents: true,
         store: 'my-store',
         defaultType: 'listitem'
     }
});

DataItem:

Ext.define('MyApp.view.ListItem', {
    extend: 'Ext.dataview.component.DataItem',
    alias: 'widget.listitem',
    config: {
        layout: ...
        items: [{
            xtype: 'component',
            itemId: 'description',
            html: '',
            flex: 2
        },
        {
            xtype: 'button',
            text: 'a button',
            itemId: ...,
            flex: ...
         },
         {
             ... another button
         }]
     },
     updateRecord: function(record) {
         ...
         this.down('#description').setHtml(record.get('description'));
         // record.get('description') does give me an undefined value
     }
});

Assuming my stores and models are set up properly, what could the problem be?

Alternatively, maybe I should just use a standard list, but set the width to <100%, and just add 2 buttons to the right for each row. Though I'd rather get the current approach to work...

Edit:
Ended up using the dataMap approach. My DataItem now looks like:

config: {
    layout: {
        type: 'hbox',
        align: 'center'
    },
    dataMap: {
        getDescription: {
            setHtml: 'description'
        }
    },
    description: {
        flex: 1
    }
},
applyDescription: function(config) {
    return Ext.factory(config, Ext.Component, this.getDescription());
},
updateDescription...

Basically like this.

I see the labels now, but am stuck on how to get a button in there. Since I don't want to link it to a store, I don't want to put it in the dataMap. I tried putting it in items, but to no avail.

Edit 2:
Well, getting the button to display was easier than I thought. It's just a repeat of what I did with the label, but without including it in the dataMap - yesButton: {...}, applyYesButton: f(){...}, updateYesButton: f(){...}...

The last issue I need to resolve is, how to uniquely identify them. I want a listener on the button, but somehow pass in the record into the handler.


Solution

  • My solution for getting a button in a dataview without linking it to the store. It's actually, somewhat unsurprisingly, similar to this blog post.

    view - ListItem.js

    ...
    config: {
        layout: {
           type: 'hbox',
           align: 'center'
        },
        dataMap: {
            getDescription: {
                setHtml: 'description'
            }
        },
        description: {
            cls: ...,
            flex: 4
        },
        myButton: {
            cls: ...,
            text: 'Button!',
            flex: 1
        }
    },
    applyDescription, updateDescription (same as in the question),
    applyMyButton: function(config) {
        return Ext.factory(config, Ext.Button, this.getMyButton());
    },
    updateMyButton: function(newButton, oldButton) {
        ... same logic as the other update method
    }
    

    In my dataview:

    ...
    config: {
        itemId: ...,
        store: ...,
        useComponents: true,
        defaultType: 'listitem',
        width: '100%',
        flex: 1,
        listeners: {
            itemtap: function(dataview, index, element, evt) {
                var store = dataview.getStore();
                var record = store.getAt(index);
                ...
            }
        }
    }
    ...