Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-16126] iOS: listView and listItem index not being updated after delete

GitHub Issuen/a
TypeBug
PriorityHigh
StatusClosed
ResolutionFixed
Resolution Date2014-01-09T20:05:40.000+0000
Affected Version/sRelease 3.1.3, Release 3.2.0
Fix Version/s2014 Sprint 01, 2014 Sprint 01 API, Release 3.2.1, Release 3.3.0
ComponentsiOS
Labelsindex, listview, module_listview, qe-testadded, support, supportTeam
ReporterMarco Cota
AssigneeVishal Duggal
Created2014-01-03T22:19:48.000+0000
Updated2014-07-23T10:05:06.000+0000

Description

Issue

When working with the listView user delete a listItem from a section trough a button event bound in the template, after the item is deleted the remaining items will keep the original sectionIndex and itemIndex value, if we try to delete elements from the same section we will start receiving Warning about the item not being in range to be deleted and elements will remain on the listView. Also after deleting a section the delete function stops working, we also notice the index of the listView remains calling elements from one section in another.

Steps to repro

1. Run the test code. 2. Click Section 0 title:"item 0" label and will be deleted correctly. 3. Click Section 0 title:"item 1" label and will delete "item 2" as this is located in section 0 item 1 index. 4. Click Section 0 title:"item 3" label and will throw a warning. 5. Click Section 1 title:"item 0" label deleting the element and section correctly. 6. Click Section 2 title:"item 0" label throwing an exception

Logs

{quote} [WARN] : ListView: Delete item index is out of range {quote} {quote} [UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2903.23/UITableView.m:1330 {quote}

Test Case

index.xml
<Alloy>
	<Window title="Win">
		
        <ListView id="eventsList" class="eventsList" defaultItemTemplate="templateItem">
            <Templates>
                <ItemTemplate  id="templateItem" name="templateItem"  class="templateItem">             
	                <Label id="title" bindId="title" class="title" onClick="doClick"/>
                </ItemTemplate>
            </Templates>
            
            <ListSection headerTitle="Section 0">
                <ListItem title:text="Item 0" />
                <ListItem title:text="Item 1" />
                <ListItem title:text="Item 2" />
                <ListItem title:text="Item 3" />
                <ListItem title:text="Item 4" />
            </ListSection>
            <ListSection headerTitle="Section 1">
                <ListItem title:text="Item 0" />
            </ListSection>
            <ListSection headerTitle="Section 2">
                <ListItem title:text="Item 0" />
                <ListItem title:text="Item 1" />
                <ListItem title:text="Item 2" />
                <ListItem title:text="Item 3" />
            </ListSection>
            <ListSection headerTitle="Section 3">
                <ListItem title:text="Item 0" />
                <ListItem title:text="Item 1" />
                <ListItem title:text="Item 2" />
            </ListSection>
        </ListView>
		
	</Window>
</Alloy>
index.js

function doClick(e){
	Ti.API.info('Section: '+e.sectionIndex+' ::: Item: '+e.itemIndex);
	$.eventsList.sections[e.sectionIndex].deleteItemsAt(e.itemIndex,1);
	if($.eventsList.sections[e.sectionIndex].items.length == 0){
			$.eventsList.deleteSectionAt(e.sectionIndex);
		}
}

$.index.open();

Comments

  1. Vishal Duggal 2014-01-09

    Common JS test code. To test make sure that the sectionIndex and itemIndex in the click and item click event handlers match. Also ensure that bugs reported above are resolved.
       var win = Ti.UI.createWindow({backgroundColor: 'white', fullscreen:true});
       
       function delayDelete(e)
       {
           Ti.API.info('DELAY Section: '+e.sectionIndex+' ::: Item: '+e.itemIndex);
           
       }
       
       function doClick(e){
           Ti.API.info('CLICK Section: '+e.sectionIndex+' ::: Item: '+e.itemIndex);
       
           if(listView.sections[e.sectionIndex].items.length == 1) {
               listView.deleteSectionAt(e.sectionIndex);
           } else {
               listView.sections[e.sectionIndex].deleteItemsAt(e.itemIndex,1);
           } 
       }
       
       var myTemplate = {
           childTemplates: [
               {                            // Title 
                   type: 'Ti.UI.Label',     // Use a label for the title 
                   bindId: 'title',          // Maps to a custom info property of the item data
               }
           ],
           events: {click: doClick}
       };
       
       var listView = Ti.UI.createListView({
           templates: { 'template': myTemplate },
           defaultItemTemplate: 'template'
       });
       var sections = [];
       
       var section0 = Ti.UI.createListSection({ headerTitle: 'Section0'});
       var dataSet0 = [
           { title: {text: 'Item 0'},},
           { title: {text: 'Item 1'},},
           { title: {text: 'Item 2'},},
           { title: {text: 'Item 3'},},
           { title: {text: 'Item 4'},}
       ];
       section0.setItems(dataSet0);
       sections.push(section0);
       
       var section1 = Ti.UI.createListSection({ headerTitle: 'Section1'});
       var dataSet1 = [
           { title: {text: 'Item 0'},}
       ];
       section1.setItems(dataSet1);
       sections.push(section1);
       
       var section2 = Ti.UI.createListSection({ headerTitle: 'Section2'});
       var dataSet2 = [
           { title: {text: 'Item 0'},},
           { title: {text: 'Item 1'},},
           { title: {text: 'Item 2'},},
           { title: {text: 'Item 3'},}
       ];
       section2.setItems(dataSet2);
       sections.push(section2);
       
       var section3 = Ti.UI.createListSection({ headerTitle: 'Section3'});
       var dataSet3 = [
           { title: {text: 'Item 0'},},
           { title: {text: 'Item 1'},},
           { title: {text: 'Item 2'},}
       ];
       section3.setItems(dataSet3);
       sections.push(section3);
       
       
       listView.setSections(sections);
       
       listView.addEventListener('itemclick',function(e){
           Ti.API.info('ITEMCLICK Section: '+e.sectionIndex+' ::: Item: '+e.itemIndex);
           
       })
       
       win.add(listView);
       win.open();
       
  2. Vishal Duggal 2014-01-09

    Pull pending against master https://github.com/appcelerator/titanium_mobile/pull/5199 Backport to 3_2_X https://github.com/appcelerator/titanium_mobile/pull/5200
  3. Wilson Luu 2014-01-17

  4. Wilson Luu 2014-01-21

    Closing ticket as fixed. Verified using both the Alloy sample app and Vishal's sample app that items are being removed correctly and the sectionIndex and itemIndex are being displayed correctly. Tested on: Appcelerator Studio, build: 3.2.1.201401151647 SDK build: 3.2.1.v20140117222448, 3.3.0.v20140117222449 CLI: 3.2.1 (git://github.com/appcelerator/titanium.git#3_2_X) Xcode: 5.0.2 Devices: iphone 5 (6.1.3), iphone 5 (7.0.2)

JSON Source