1

I am creating a page to have both Invoice and Invoice Line item on same page and provided the option to add or remove lines on the form. But for some reason validation rules are fired when I try to remove the line from the from. there is no DML involved , I am justmaintaining a list in a Controller and adding and removing the LineItem from the List. 

<apex:page standardController="BT_INVOICE__c" extensions="BT_InvoiceControllerExtension">
<apex:form >
    <apex:pageBlock mode="detail">
        <apex:pageBlockButtons location="bottom">
            <apex:commandButton action="{!save}" value="Save"/> 
            <apex:commandButton action="{!cancel}" value="Cancel"/>
            <apex:commandButton action="{!addLine}" value="More lines"/>  
            <apex:commandButton action="{!removeLine}" value="Remove lines" rerender="wtable"/> 
             <apex:commandButton value="Add Row" action="{!addLine}" rerender="wtable"/>
                     
        </apex:pageBlockButtons>
        <apex:pageBlockSection columns="1" title="Invoice">
                <apex:inputField value="{! BT_INVOICE__c.VENDOR__c}"/>
        </apex:pageBlockSection>
        <apex:pageBlockSection title="Invoice Line">
            <apex:pageblocktable value="{!invoiceLinesWrapper}" ID="wtable" var="invoiceLineWrapper">
            
                 <apex:column headerValue="General Ledger Account">
                    <apex:inputField value="{!invoiceLineWrapper.line.GENERAL_LEDGER_ACCOUNT__c }"/>
                  </apex:column>
                  
                  <apex:column headerValue="Product">
                         <apex:inputField value="{!invoiceLineWrapper.line.PRODUCT__c }"/>
                 </apex:column>
                 
                   <apex:column headerValue="Qty">
                          <apex:inputField value="{!invoiceLineWrapper.line.QUANTITY__c }"/>
                 </apex:column>
                 
                    <apex:column headerValue="Unit Price">
                            <apex:inputField value="{!invoiceLineWrapper.line.UNIT_PRICE__c }"/>
                 </apex:column> 
                 <apex:column headerValue="Action">
                     <apex:commandButton value="Delete" action="{!removeLine}" rerender="wtable">
                         <apex:param name="toDelete" value="{!invoiceLineWrapper.index}" assignTo="{!toDelete}"/> 
                      </apex:commandButton>
                 </apex:column> 
              </apex:pageblocktable>
              
        </apex:pageBlockSection>
    </apex:pageBlock>
    <apex:pageMessages />
</apex:form>
</apex:page>

public with sharing class BT_InvoiceControllerExtension {

private BT_INVOICE__c invoice;

private Integer currIndex =0;

public Integer toDelete {get; set;}

private List<BT_INVOICE_LINE_ITEM__c> invoiceLines = new List<BT_INVOICE_LINE_ITEM__c>() ;

public List<InvoiceLineWraper> invoiceLinesWrapper {get; set;}

    public BT_InvoiceControllerExtension(ApexPages.StandardController controller) {
        invoice = (BT_INVOICE__c)controller.getRecord();
        invoiceLinesWrapper = new List<InvoiceLineWraper>();
        invoiceLinesWrapper.add(new InvoiceLineWraper(0));
        currIndex = 1;
    }
    
    public List<BT_INVOICE_LINE_ITEM__c> getInvoiceLinesItem() {
        
        return invoiceLines;
    }
    
    public PageReference save() {
    /*
          insert invoice;
          for(BT_INVOICE_LINE_ITEM__c lineItem:invoiceLines){
          lineItem.INVOICE__c= invoice.ID;
          }
          insert invoiceLines;
           */
       return new PageReference('/' + invoice.Id);
      
   }
   
   public void addLine()  {
       invoiceLinesWrapper.add(new InvoiceLineWraper(currIndex++));
   }
   
  public void removeLine()
   {
    Integer toDelPos=-1;
       for (Integer idx=0; idx<invoiceLinesWrapper.size(); idx++){
           if (invoiceLinesWrapper[idx].index == toDelete){
               toDelPos=idx;
           }
      }
      if (-1!=toDelPos){
          invoiceLinesWrapper.remove(toDelPos);
     }
}
   
   public class InvoiceLineWraper {
   
   public BT_INVOICE_LINE_ITEM__c line {get; set;}
   
   public Integer index {get; set;}
   
     public InvoiceLineWraper(Integer inIndex)
     {
          index=inIndex;
          line= new BT_INVOICE_LINE_ITEM__c();
     }
     
    }
   

}

1 Answer 1

4

When you need to remove lines like this typically you would:

  1. use immediate=true on the action to bypass validation

     <apex:commandButton action="{!removeLine}" value="Remove lines" rerender="stable" immediate="true"/> 
    

A Boolean value that specifies whether the action associated with this component should happen immediately, without processing any validation rules associated with the fields on the page. If set to true, the action happens immediately and validation rules are skipped. If not specified, this value defaults to false.

  1. Possibly Wrap the section of the page in an action region (may or may not be required based on your page and everything going on so make sure you test it out with all actions the page performs)

This only needs to be done if you need to submit values from the fields when clicking the remove line, otherwise you do not need it

An area of a Visualforce page that demarcates which components should be processed by the Force.com server when an AJAX request is generated. Only the components in the body of the are processed by the server, thereby increasing the performance of the page

It may be needed if you are removing a line and have entered values in the other lines and have not saved those values yet when you click on remove lines. However I have not tested this theory. So I am swapping the order here as immediate = true should be #1

An example answer regarding this: Problem in commandbutton with immediate="true"

    <apex:actionregion>
        <apex:pageblocktable value="{!invoiceLinesWrapper}" ID="wtable" var="invoiceLineWrapper">

                 <apex:column headerValue="General Ledger Account">
                    <apex:inputField value="{!invoiceLineWrapper.line.GENERAL_LEDGER_ACCOUNT__c }"/>
                  </apex:column>

                  <apex:column headerValue="Product">
                         <apex:inputField value="{!invoiceLineWrapper.line.PRODUCT__c }"/>
                 </apex:column>

                   <apex:column headerValue="Qty">
                          <apex:inputField value="{!invoiceLineWrapper.line.QUANTITY__c }"/>
                 </apex:column>

                    <apex:column headerValue="Unit Price">
                            <apex:inputField value="{!invoiceLineWrapper.line.UNIT_PRICE__c }"/>
                 </apex:column> 
                 <apex:column headerValue="Action">
                     <apex:commandButton value="Delete" action="{!removeLine}" rerender="wtable">
                         <apex:param name="toDelete" value="{!invoiceLineWrapper.index}" assignTo="{!toDelete}"/> 
                      </apex:commandButton>
                 </apex:column> 
              </apex:pageblocktable>
     </apex:actionRegion>
3
  • I was just going to recommend #2. Can you add a little more detail around why #1 actually helps? It's pretty hand-wavy currently and I'm actually not sure myself.
    – Adrian Larson
    Sep 10, 2016 at 23:10
  • 1
    @AdrianLarson - Added some stuff. i do not think it will be needed here and I am unclear of its use in this context as I rarely use it.
    – Eric
    Sep 10, 2016 at 23:17
  • Yeah, I've never needed it either. Well with the new ordering now my comment looks silly. :P Glad I'm not the only one unfamiliar with the use cases for that tag.
    – Adrian Larson
    Sep 10, 2016 at 23:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .