2

For some reason, that field in the wrapper class is not picking up the value entered into the VF page. I have sample created visualforce page and apex class, as soon as hit the Add More button it clears all the values in the <apex: inputText I'm not sure what I'm doing wrong here, anybody?

PS: my custom class SpecificTimeClass

Visualforce page:

<apex:pageblock id="thePB" title="Creating Multiple">
  <apex:pageblockButtons >
   <apex:commandButton value="Save" action="{!SaveMultipleAccounts}"  reRender="accountHead"/>  
  </apex:pageblockButtons>

  <apex:outputPanel id="accountHead">

  <apex:variable value="{!0}" var="rowNum"/>  
   <apex:pageBlockSection columns="1" title="Adding Multiple" id="thePbs" collapsible="False"> 

     <apex:pageBlockTable value="{!waAccList}" var="eachRecord"> 

      <apex:column headerValue="Action">
      </apex:column>

      <apex:column headerValue="From Time">
          <apex:inputText value="{!eachRecord.record.iFrom}" required="true"/>
       </apex:column>

      <apex:column headerValue="To Time">
           <apex:inputText value="{!eachRecord.record.iTo}" required="true"/>
       </apex:column>

    </apex:pageBlockTable>
   </apex:pageBlockSection>
   <apex:commandButton value="Add More" action="{!addNewRowToAccList}" rerender="accountHead" Status="status" immediate="true" />   
  </apex:outputPanel> 
</apex:pageblock>

Apex class:

public class fromToController 
{
    public List<WrapperpaAccountList> waAccList {get;set;}

    public PageReference SaveMultipleAccounts() 
    {
        system.debug('controller save method is calling-->');
        save(waAccList);
        system.debug('controller save method is calling-->' + waAccList);
        system.debug('waAccList >>>' + waAccList );
        return null;
    }

    public fromToController()
    {
        waAccList = new List<WrapperpaAccountList>();
        addNewRowToAccList();
    }

    public void addNewRowToAccList()
    {
        waAccList = addNewRowToAccList(waAccList);
        system.debug('addNewRowToAccList waAccList >>>' + waAccList );
    }

     public static List<WrapperpaAccountList> addNewRowToAccList(List<WrapperpaAccountList> waAccObjList){

        WrapperpaAccountList newRecord = new WrapperpaAccountList();
        SpecificTimeClass newAccountRecord = new SpecificTimeClass();        
        newRecord.record = newAccountRecord;
        newRecord.index = waAccObjList.size();
        waAccObjList.add(newRecord);
        system.debug('addNewRowToAccList >>>' + waAccObjList);
        return waAccObjList;
    }

    public class SpecificTimeClass
    {
        public integer iFrom {get; set;}
        public integer iTo {get;set;}            
    }

    public class WrapperpaAccountList
    {
        public Integer index {get;set;}
        public SpecificTimeClass record {get;set;}
    } 

    //save a record:    
    public static void save(List<WrapperpaAccountList> waAccList) 
    {
        system.debug('==waAccList==>'+waAccList.size());
        List<SpecificTimeClass> accountRecordsToBeInserted = new List<SpecificTimeClass>();
        if(waAccList !=null && !waAccList.isEmpty())
        {
            for(WrapperpaAccountList eachRecord : waAccList ){
                SpecificTimeClass accTemp = eachRecord.record;
                accountRecordsToBeInserted.add(accTemp);

            }
            system.debug('==accountRecordsToBeInserted==>'+accountRecordsToBeInserted.size());
            //insert accountRecordsToBeInserted;
        }
    }

}

3 Answers 3

1

I believe your problem is that you're throwing the data away! I'm not sure why you're using a static method to implement the add row function, but the real problem is you're overwriting your existing list every time you add a new row.

In addNewRowToAccList you're overwriting the controller's list member variable with the return value of the static addNewRowToAccList:

waAccList = addNewRowToAccList(waAccList);

First thing to do is try and avoid some confusing by using different names for the two methods, so let's change the static method to be called addNewRowToList, and we'll remove the return type:

public static void addNewRowToList(List<WrapperpaAccountList> waAccObjList)
{

Now, lists are passed by reference, meaning inside of addNewRowToList we're working with the same instance of the list that's being passed in, so any changes to it are actually being made to that original list.

This means you don't need to return a new value, and you definitely don't need to create a new instance inside of it:

public static void addNewRowToList(List<WrapperpaAccountList> waAccObjList)
{
    SpecificTimeClass newAccountRecord = new SpecificTimeClass();        
    newRecord.record = newAccountRecord;
    newRecord.index = waAccObjList.size();
    waAccObjList.add(newRecord);
    system.debug('addNewRowToAccList >>>' + waAccObjList);
}

This will add a new record to your existing list, and unlike before won't replace your list with a brand new one which is what was discarding your data.

5
  • Return type should be void. Only constructors do not have a return type.
    – sfdcfox
    Jun 6, 2016 at 1:14
  • Fixed! Just deleted the old one and forgot to add it in.
    – Matt Lacey
    Jun 6, 2016 at 1:19
  • @LaceySnr: the reason those static methods are there due to i copy from helper class.... however, based on your answer i do not see the return type addNewRowToList for this method? can you please post the entire code, if i have the code you have posted then i'm getting all sort of erros...
    – Nick
    Jun 6, 2016 at 3:30
  • I missed the void return type the first time around, that might be the cause of the errors you're seeing. You don't need a return type because the method updates the list passed in.
    – Matt Lacey
    Jun 6, 2016 at 4:32
  • did not work even after making the changes, still the same behaviour as described in my question. where is the newRecord variable coming from? in addNewRowToList error: Variable does not exist: newRecord.record
    – Nick
    Jun 6, 2016 at 13:20
1

I think the problem is with the attribute immediate that used in <apex:commandButton>. Whenever we use this attribute that time no validation rules are called and no setter is called for the field. You can visit following links for more detail:

Problem in commandbutton with immediate="true"

https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_commandButton.htm

You can use below code:

<apex:outputPanel > <input type="button" onclick="addNewLine()" value="New Line"/> </apex:outputPanel>

addNewLine is an action function that called controller method. After completion of method, you should rerender the pagaBlockSection so that new values bid to controller and displayed on VF page.

3
  • if I remove the immedidate=true then I could not able to add more, you can try copy and paste the code in your org
    – Nick
    Jun 6, 2016 at 13:12
  • You can try the edited code in my comment. Let me know if it helps to you. Jun 7, 2016 at 5:46
  • I have paste your code in my org and I got the values successfully and all my debugs work properly. I'm confused now that what is your problem. Jun 7, 2016 at 5:57
0

I gave it a try in dev org and things worked well with below code:

<apex:pageMessages id="pagemsg"></apex:pageMessages>
<apex:form >


  <apex:pageblock id="thePB" title="Creating Multiple">
  <apex:pageblockButtons >
   <apex:commandButton value="Save" action="{!SaveMultipleAccounts}"  reRender="accountHead"/>  
  </apex:pageblockButtons>

  <apex:outputPanel id="accountHead">

  <apex:variable value="{!0}" var="rowNum"/>  
   <apex:pageBlockSection columns="1" title="Adding Multiple" id="thePbs" collapsible="False"> 

     <apex:pageBlockTable value="{!waAccList}" var="eachRecord"> 

      <apex:column headerValue="Action">
      </apex:column>

      <apex:column headerValue="From Time">
          <apex:inputText value="{!eachRecord.record.iFrom}" required="true"/>
       </apex:column>

      <apex:column headerValue="To Time">
           <apex:inputText value="{!eachRecord.record.iTo}" required="true"/>
       </apex:column>

    </apex:pageBlockTable>
   </apex:pageBlockSection>
   <apex:commandButton value="Add More" action="{!addNewRowToAccList}" rerender="accountHead,pagemsg" Status="status"  />   
  </apex:outputPanel> 
</apex:pageblock>

Explanations:

  1. As you are using required="true" you must always enter some valid number value in inputs before clicking "Add More". As <apex:pageMessages id="pagemsg"></apex:pageMessages> was not there in your VF code you were not able to see what was going wrong when clicking "Add More".

  2. Immediate="true" was removed as it was clearing the whole form fields. This was required just to overcome problems coming because of Required="true" which was handled in above modified code.

  3. There were no code changes required at controller side.

You must log in to answer this question.

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