By default, tapping a row in an Enyo list will “select” it. Sometime you might want finer-grained control over when selection happens and this post will offer a means to accomplish just that.
Selection is managed by an instance of enyo.Selection which is owned by the List control. You can control how selection behaves via two passthrough properties on the List control: toggleSelected and multiSelect.
toggleSelected is false by default which means tapping the row will always select it. By setting toggleSelected to false, tapping the row will toggle the selection back and forth. multiSelect is also false by default which means only one row will be selected at a time. By setting it to true, you can select multiple row (surprising, I know).
When a row is selected or deselected, it is rerendered by the List and your onSetupItem handler is called. In addition to an index property, the event will also have a selected property that reflects the current selection state of the row. Alternatively, if you need to retrieve the selection state of the entire list, you can call getSelection() on the List to get a handle on its underlying Selection instance.
Perhaps you’ve decided to include interactive controls in your list item such as a checkbox or button and have decided that tapping those shouldn’t trigger row selection. Preventing the selection can use the same technique as triggering the selection: the tap method.
FlyweightRepeater does all the work for rendering list items using the flyweight pattern. It also implements a tap() method to catch any taps on child nodes to trigger selection. So, if you want to prevent selection, all you have to do is return true in your ontap handler to cancel bubbling thereby preventing the selection trigger.
What if you had several buttons and only wanted one control (like a checkbox) to control selection? Turns out that any subkind of Control can override tap() to handle ontap events (even without specifying an entry in your handlers hash!) because Control already declares the handler. So, if you create a custom kind which implements tap() to return true, selection will never be triggered. By adding a little exception logical to tap(), you can decide when selection occurs rather than on every tap.
Here’s a working example:
enyo.kind({
name:"SimpleRow",
kind:"Control",
classes:"simple-row",
published:{
title:""
},
components:[
{name:"cb", kind:"Button", content:"Select", ontap:"cbTapped"},
{name:"title"}
],
create:function() {
this.inherited(arguments);
this.titleChanged();
},
titleChanged:function() {
this.$.title.setContent(this.title);
},
cbTapped:function(source, event) {
// nothing magical about this property, just made it up
event.allowBubble = true;
},
tap:function(source, event) {
if(event.allowBubble) {
event.allowBubble = false;
} else {
// cancel bubble without my special flag
return true;
}
}
});
enyo.kind({
name:"ex.App",
components:[
{kind:"List", toggleSelected:true, count:25, onSetupItem:"setupItem", components:[
{name:"sr", kind:"SimpleRow"}
]}
],
setupItem:function(source, event) {
this.$.sr.setTitle("Item " + event.index);this.$.sr.addRemoveClass("selected", event.selected);
}
});
new ex.App().renderInto(document.body);