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
tdeptdep 

Update index values in List upon removal (List out of bounds error)

I am currently having an issue with a dynamic list that has the ability to add rows as needed. This functionality is working fine but I am running into an issue with the deletion of rows.

 

The user has the ability to add 1 row or 25 rows. Each row has the ability to be removed from the entry page. Issue is when they add 25 rows (or even a few) and delete a row in the middle of the list then go to delete a higher value row it will produce the list out of bounds error.

 

Example: User adds 25 rows. They need to delete row 15 and 20. User removed 15 first and when they go to delete 20 it crashes with a list out of bounds exception.

 

I understand why it does this but am trying to figure out how to re-assign index values once the list is modified.

 

Here is the delete method as it stands right now:

    public void DelPersonnel()
    {   system.debug('selected row index---->'+selectedRowIndex);   
         if(count != 1) //Prevent crash on remove 1
        {
             lstInner.remove(Integer.valueOf(selectedRowIndex)-1);
             //something needs to go here to change the row values!  
             count = count - 1;
             numpersonnel = numpersonnel - 1;
        }
    }

 

I am assuming I need to add a for loop to reassign row index values over the deleted - can anyone assist? I am unsure on how to change the index value.

 

Thanks in advance

mast0rmast0r

Provide the code of your list lstInner, how do you implement it.

tdeptdep

Apex:

public class citygizmo {

public string unitid = System.currentPagereference().getParameters().get('u'); 
public string getunitid() { return unitid; }

public City_Unit__c unitinfo;

//Grab city unit info
public City_Unit__c getunitinfo(){
   unitinfo = [Select ID, Name, Agency_Name__c, Agency_Name_Other__c, Borough__c, City__c, Contact_Email_Address__c, Contact_Phone_Number__c, Date__c, 
                                        First_Name__c, Friday_Finish__c, Friday_Start__c, Last_Name__c, Monday_Finish__c, Monday_Start__c, Saturday_Finish__c, 
                                          Saturday_Start__c, Spaces_Managed__c, Spaces_Managed_Other__c, State__c, Sunday_Finish__c, Sunday_Start__c, Thursday_Finish__c, 
                                            Thursday_Start__c, Title__c, Tuesday_Finish__c, Tuesday_Start__c, Unit_Department_Division_Name__c, Unit_Department_Division_Street_Address__c, 
                                              Wednesday_Finish__c, Wednesday_Start__c, Zip__c, Complete_Contact_Info__c FROM City_Unit__c WHERE ID = :unitid];
    return unitinfo;                                             
}          

public string infocomplete {get;set;}

public void savecontactinfo()
{
unitinfo.Complete_Contact_Info__c = true;
update unitinfo;
}

//BEGIN PERSONNEL COLLECTION:
    //will hold the records to be saved
    public List<City_Personnel__c>lstforc = new List<City_Personnel__c>();
    
    //list of the inner class
    public List<innerClass> lstInner 
    {   get;set;    }
    
    //will indicate the row to be deleted
    public String selectedRowIndex
    {get;set;}
    
    //no. of rows added/records in the inner class list
    public Integer count = 1;
    //{get;set;}

    public Integer numpersonnel
    {get;set;}
    
    ////save the records by adding the elements in the inner class list to lstforc,return to the same page
    public PageReference Save()
    {
        PageReference pr = new PageReference('/apex/citygizmo');
        
        for(Integer j = 0;j<lstInner.size();j++)
        {
            lstforc.add(lstInner[j].person);
        } 
        insert lstforc;
        pr.setRedirect(True);
        return pr;
    }
        
    //add one more row
    public void AddPersonnel()
    {   
        count = count+1;
        numpersonnel = count;
        addMorePersonnel();      
    }
    
    public void Add25Personnel()
    {   
        for(integer i = 0; i < 25; i++)
        {
        count = count+1;
        numpersonnel = count;
        addMorePersonnel();
        }    
    }
        
    ///Begin addMore
    public void addMorePersonnel()
    {
        //call to the iner class constructor
        innerClass objInnerClass = new innerClass(count);
        
        //add the record to the inner class list
        lstInner.add(objInnerClass);    
        system.debug('lstInner---->'+lstInner);            
    }    

    public void add25MorePersonnel()
    {
        for(integer i = 0; i < 25; i++)
        {
        innerClass objInnerClass = new innerClass(count);
        
        //add the record to the inner class list
        lstInner.add(objInnerClass);
        system.debug('lstInner---->'+lstInner);
        }
    }       
    
    public void DelPersonnel()
    {   system.debug('selected row index---->'+selectedRowIndex);   
         if(count != 1) //Prevent crash on remove 1
        {
             lstInner.remove(Integer.valueOf(selectedRowIndex)-1);
             //something needs to go here to change the row values!  
             count = count - 1;
             numpersonnel = numpersonnel - 1;
        }
    }
    
    public citygizmo() //Constructor
    {   numpersonnel = 1;
        lstInner = new List<innerClass>();
        addMorePersonnel();
        selectedRowIndex = '0';   
    }
        
    //Inner Class
    public class innerClass
    {       
        //recCount acts as a index for a row. This will be helpful to identify the row to be deleted
        public String recCount
        {get;set;}
        
        public City_Personnel__c person
        {get;set;}
        
        //Inner Class Constructor
        public innerClass(Integer intCount)
        {
            recCount = String.valueOf(intCount);        
            
            //create a new account
            person = new City_Personnel__c();
            
        }//End Inner class Constructor    
    }//End inner Class

}

 

 

VF:

<apex:form >
<div class="header">Personnel</div>
<br />
<!-- <apex:commandbutton value="Save" action="{!Save}" rerender="pb1"/> -->
    
        <apex:outputpanel id="pb1">
        <apex:commandbutton value="Add  1 Row"  action="{!AddPersonnel}" rerender="pb1"/> &nbsp; &nbsp;
        <apex:commandbutton value="Add 25 Rows" action="{!Add25Personnel}" rerender="pb1"/>
        &nbsp;&nbsp; Total Personnel Added: {!numpersonnel}

        <table>
        <tr>        
        <td width="3"></td><td width="135">Name</td><td width="137">Title</td><td width="140">Civil Service Title</td>
        <td width="174">Job Classification</td><td width="120">Status</td><td>Remove</td>
        </tr>
        </table>
        
        <apex:repeat value="{!lstInner}" var="e1" id="therepeat">
            <apex:panelGrid columns="6">
                  
                <apex:panelGrid title="Name" >
                   <!-- <apex:facet name="header">Name</apex:facet> -->
                    <apex:inputfield styleclass="input" value="{!e1.person.Name}"/>
                </apex:panelGrid>
                
                <apex:panelGrid title="Office Title" >
                   <!-- <apex:facet name="header">Office Title</apex:facet> -->
                    <apex:inputfield styleclass="input" value="{!e1.person.Office_Title__c}"/>
                </apex:panelGrid>
                
                <apex:panelGrid title="Civil Service Title" >
                   <!-- <apex:facet name="header">Civil Service Title</apex:facet> -->
                    <apex:inputfield styleclass="input" value="{!e1.person.Civil_Service_Title__c}"/>
                </apex:panelGrid>
                
                <apex:panelGrid title="Job Classification" >
                   <!-- <apex:facet name="header">Job Classification</apex:facet> -->
                    <apex:inputfield styleclass="input" value="{!e1.person.Job_Classification__c}"/>
                </apex:panelGrid>
                
                <apex:panelGrid title="Status" >
                  <!--  <apex:facet name="header">Job Classification</apex:facet> -->
                    <apex:inputfield styleclass="input" value="{!e1.person.Status__c}"/>
                </apex:panelGrid>
                
                <apex:panelGrid headerClass="Remove">
                    <!-- <apex:facet name="header">Del</apex:facet> -->
                    <apex:commandButton value="X" action="{!DelPersonnel}" rerender="pb1">
                        <apex:param name="rowToBeDeleted" value="{!e1.recCount}" assignTo="{!selectedRowIndex}"></apex:param>
                    </apex:commandButton>
                </apex:panelGrid>

           </apex:panelGrid>   
        </apex:repeat>
      
    </apex:outputpanel>
   </apex:form> 

 

sfdcfoxsfdcfox

I don't have time to write out an entire sample, but here's how I generally approach this issue:

 

public with sharing class Controller {
  public void removeRow(RowItem item) {
    for(integer i = 0; i < rows.size(); i++) {
       if(rows[i] == item) {
         rows.remove(i);
         break;
       }
    }
  }

  public RowItem[] rows { get; set; }

  public class RowItem {
    private Controller parentController;
    public RowItem(Controller parentController) {
      this.parentController = parentController;
    }
    public void removeRow() {
      this.parentController.removeRow(this);
    }
  }
public Integer rowCount() {
return rows.size();
} }

 

<apex:pageBlockTable value="{!rows}" var="row">
  <apex:column headerValue="Actions">
    <apex:commandLink value="Del" action="{!row.removeRow}"/>
  </apex:column>
</apex:pageBlockTable>

In other words, the size is determined by the collection, which already knows how large it is. Try not to duplicate logic that's already available. Note that I don't have to store the index of the inner class in each row, as the parent object knows how to handle which row is being removed. The row item requests for its own removal, and the main controller satisfies this request.