function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Siddharth ManiSiddharth Mani 

List index out of bounds exception in Wrapper Class Deletion

hi,

I am trying to remove items being displayed on a VF page via wrapper class. The code seems to work fine when a single record is selected but throws index out of bounds exception when multiple entries are selected. Below is the code:

Controller:
public with sharing class SelectEmpRecordController2 {
     //Our collection of the class/wrapper objects wrapEmployee
    public List<wrapEmployee> wrapEmpList{get; set;}
    public List<Employee_Information__c> selectedEmployees{get;set;}
    public Map<String,Double> empatt{get;set;}
 
    public SelectEmpRecordController2(){
        if(wrapEmpList== null) {
            wrapEmpList = new List<wrapEmployee>();
            for(Employee_Information__c s: [select Name,Emp_Name__c,Percentage__c from Employee_Information__c]) {
                // As each employee is processed we create a new wrapEmp object and add it to the wrapEmpList
                wrapEmpList.add(new wrapEmployee(s));
            }
        }
        if(empatt == null) {
            empatt = new Map<String,Double>();
            for(Employee_Information__c s: [select Name,Emp_Name__c,Percentage__c from Employee_Information__c]) {
                empatt.put(s.Emp_Name__c,s.Percentage__c);
            }
            system.debug('map value'+empatt);
        }
    }
 
    public void processSelected() {
    selectedEmployees = new List<Employee_Information__c>();
 
        for(wrapEmployee wrapEmpObj : wrapEmpList) {
            if(wrapEmpObj.selected == true) {
                selectedEmployees.add(wrapEmpObj.emp);
                wrapEmpObj.perc = empatt.get((wrapEmpObj.emp).Emp_Name__c);
            }
        }
    }
    
    public void removeEmployee() {
        Set<Integer> toDelete = new Set<Integer>();
        for(Integer i=0;i<wrapEmpList.size();i++) {
            if(wrapEmpList[i].selected == true) {
                toDelete.add(i);
            }
        }
        for(Integer i : toDelete) {
            wrapEmpList.remove(i);
        }
    }
 
    // This is our wrapper/container class. This wrapper class contains both the salesforce object Employee_Information__c and a Boolean value
    public class wrapEmployee{
        public Employee_Information__c emp {get; set;}
        public Boolean selected {get; set;}
        public double perc{get;set;}
         
        public wrapEmployee(Employee_Information__c s) {
            emp = s;
            selected = false;
        }
        
    }
}

VF Page
<apex:page controller="SelectEmpRecordController2" sidebar="false">
    <script type="text/javascript">
        function selectAllCheckboxes(obj,receivedInputID){
            var inputCheckBox = document.getElementsByTagName("input");
            for(var i=0; i<inputCheckBox.length; i++){
                if(inputCheckBox[i].id.indexOf(receivedInputID)!=-1){
                    inputCheckBox[i].checked = obj.checked;
                }
            }
        }
    </script>
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockButtons >
                <apex:commandButton value="Show Selected Employee Result" action="{!processSelected}" rerender="table2"/>
                <apex:commandButton value="Remove Employee" action="{!removeEmployee}" rerender="table"/>
            </apex:pageBlockButtons>
 
            <apex:pageblockSection title="All Employee Result" collapsible="false" columns="2">
 
                <apex:pageBlockTable value="{!wrapEmpList}" var="empWrap" id="table" title="All Results">
                    <apex:column headerValue="Option" >
                        <apex:facet name="header">
                            <apex:inputCheckbox onclick="selectAllCheckboxes(this,'inputId')"/>
                        </apex:facet>
                        <apex:inputCheckbox value="{!empWrap.selected}" id="inputId"/>
                    </apex:column>
                    <apex:column value="{!empWrap.emp.Name}" />
                    <apex:column value="{!empWrap.emp.Emp_Name__c}" />
                    <!--<apex:column value="{!empWrap.emp.Percentage__c }" />-->
                </apex:pageBlockTable>
 
                <apex:pageBlockTable value="{!selectedEmployees}" var="s" id="table2" title="Selected Employees">
                    <!--<apex:column value="{!s.Name}" headerValue="Name"/>
                    <apex:column value="{!s.Emp_Name__c}" headerValue="Employee Name"/>-->
                    <apex:column value="{!s.Percentage__c}" headerValue="Percentage" />
                </apex:pageBlockTable>
 
            </apex:pageblockSection>
        </apex:pageBlock>
    </apex:form> 
</apex:page>

Please check the removeEmployee() function for the details I mentioned.
Can anyone let me know what is wrong?
Best Answer chosen by Siddharth Mani
Siddharth ManiSiddharth Mani
Got the answer from stackexchange:
http://salesforce.stackexchange.com/questions/131975/list-index-out-of-bounds-exception-in-wrapper-class-deletion

Issue is because the list size keeps changing on iteration and hence the index goes out of bounds.
Posting the modified controller code here for others sake:
 
public void removeEmployee() {
    List<wrapEmployee> newWrapEmpList = new List<wrapEmployee>();
    for (wrapEmployee emp :wrapEmpList){
        if(emp.selected != true) {
            newWrapEmpList.add(emp);
        }
    }
    wrapEmpList = newWrapEmpList;
    //wrapEmpList = new List<wrapEmployee>(newWrapEmpList);
}