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
brielea1984brielea1984 

Creating records for each Selected Record in a Dynamically Created List Visualforce/Apex

I had this working the other day, then yesterday I erased my work thinking the client wanted something else (rookie mistake). Now I need to put it back and I can't get it to work! I think my brain got its wires crossed in the last two days...

Scenario:
  • Visualforce page for the Order object
  • On the page, created a list with checkboxes displaying the names of the Assets related the the same Account as the Order
  • On save, upsert the Order with values in the Order form and for each selected Asset in the list, I am trying to create a record passing info from the Asset
What's happening:
  • Doesn't seem to be looping through all selected checkboxes. Looking at the debug logs, only one checkbox is ever picked up.
Visualforce Page:
<apex:page standardController="Order" showHeader="false" sidebar="false" extensions="TestExtension">   

    <apex:form id="theForm">
        <apex:pageBlock title="Service Request">
            <apex:pageBlockButtons location="both">
                <apex:commandButton action="{!processSelected}" value="Continue"/>                        
            </apex:pageBlockButtons>
            
            <apex:pageBlockSection >
                <apex:inputField value="{!Order.BillToContactId}"/>
                <apex:outputField value="{!Order.OwnerId}"/>      
                <apex:inputField value="{!Order.Service_initiated_By__c}" style="width: 150px;"/>                
                <apex:outputField value="{!Order.Account.Name}"/>
                <apex:inputField value="{!Order.Description}" label="Problem Description"/>
                <apex:outputField value="{!Order.Sold_Order__c}"/>                                                
            </apex:pageBlockSection>
            
   <!--THIS IS THE DATA TABLE I'M WORKING WITH  -->    
   <apex:pageBlockSection title="Select Installed Products" columns="1">
                <apex:pageBlockTable value="{!assets}" var="a" id="table" width="1000px;" >
                    <apex:column >
                        <!-- This is our selected Boolean property in our wrapper class -->
                        <apex:inputCheckbox value="{!a.selected}"/>
                    </apex:column>
                    <apex:column value="{!a.asset.Name}"/>
                    <apex:column value="{!a.asset.Original_Order_Variant_Number__c}"/>
                    <apex:column value="{!a.asset.Install_Date__c}"/>
                    <apex:column value="{!a.asset.Location_Details__c}"/>
                </apex:pageBlockTable>
            </apex:pageBlockSection>
            
        </apex:pageBlock>
    </apex:form>   
</apex:page>
Apex Code: 
public with sharing class TestExtension {
    
    private final Order o;
    public List<aAsset> assetList {get; set;} 
    
    public TestExtension(ApexPages.StandardController stdController) {
        this.o = (Order)stdController.getRecord();       
    }
    
       
    public List<aAsset> getAssets() {
        if(assetList == null) {
            assetList = new List<aAsset>();
            for(Asset a: [SELECT Id, Name, Product2Id, Original_Order_Variant_Number__c, Install_Date__c, Location_Details__c FROM Asset WHERE AccountId = :o.AccountId]) {
                
                assetList.add(new aAsset(a));
            }
        }
        return assetList;
    }
    
<!--This is where I'm saving and trying to insert. I know I'm missing something obvious in making sure it loops through everything-->

    public PageReference processSelected() {
        
        try{    
            List<Asset> selectedAssets = new List<Asset>();
            
            for(aAsset aAsst: getAssets()) {
                if(aAsst.selected == true) {
                    selectedAssets.add(aAsst.asset);
                }
            }
            
            System.debug('These are the selected Assets...');
            for(Asset asset: selectedAssets) {
                system.debug(asset);
                
                Service_Request_Configuration__c src = new Service_Request_Configuration__c ();
                
                src.Account__c = o.AccountId;
                src.Installed_Product_Asset__c = asset.Id;
                src.Installed_Product__c = asset.Product2Id;
                src.Order__c = o.id;
                
                insert src; 
                
                o.Service_Type__c = propPickValSelected;
                upsert o;
                
                PageReference pageRef = new PageReference('/apex/RMS_createServiceOrder4?id='+ o.Id + '&retUrl=' + o.Id);
                pageRef.setRedirect(true);
                return pageRef;
            }
        }
        catch(Exception ex){
            ApexPages.addMessages(ex);
        }
        return null;
    }
    
    public class aAsset {
        public Asset asset {get; set;}
        public Boolean selected {get; set;}

        public aAsset(Asset a) {
            asset = a;
            selected = false;
        }
    }
}

Like I commented in the code, I'm fairly certain it's something obvious and simple I'm missing to get it looping through properly, but I have been staring at it too long and it's not jumping at me anymore. Any help would be much appreciated!

Thanks!

 
Best Answer chosen by brielea1984
ShivaKrishna(Freelancer)ShivaKrishna(Freelancer)
Hi there ,

Your code fine expect below three lines in method "processSelected"

  PageReference pageRef = new PageReference('/apex/RMS_createServiceOrder4?id='+ o.Id + '&retUrl=' + o.Id);
                pageRef.setRedirect(true);  ()
                return pageRef;


fist thing remove that return from for loop and place it outside
though you are creating the pagereference reference but at the end of the method you are returning null mean you are not using that as well. 
you are setting redirect to true (pageRef.setRedirect(true);  ) .. this is the real cause it makes all the parameters calculated to initial stage so that no records selected would be displayed.

I am not sure on your requirement. but this code may help you 

public PageReference processSelected() {
        PageReference pageRef = null;
        try{   
            List<Asset> selectedAssets = new List<Asset>();
             
            for(aAsset aAsst: getAssets()) {
                if(aAsst.selected == true) {
                    selectedAssets.add(aAsst.asset);
                }
            }
             
            System.debug('These are the selected Assets...');
            for(Asset asset: selectedAssets) {
                system.debug(asset);
                Service_Request_Configuration__c src = new Service_Request_Configuration__c ();
                src.Account__c = o.AccountId;
                src.Installed_Product_Asset__c = asset.Id;
                src.Installed_Product__c = asset.Product2Id;
                src.Order__c = o.id;
                insert src;
                o.Service_Type__c = propPickValSelected;
                upsert o;
            }
                pageRef = new PageReference('/apex/RMS_createServiceOrder4?id='+ o.Id + '&retUrl=' + o.Id);
                pageRef.setRedirect(true);  
        }
        catch(Exception ex){
            ApexPages.addMessages(ex);
        }
        return pageRef;
    }


use debug statement and for better back end debug.

let me know, if it helps you :)
nagasfdc1@gmail.com
 

All Answers

Kofi A. JohnsonKofi A. Johnson
Hi brielea,

You put a "return statement" (return pageRef) in the FOR LOOP at line 53. This makes the FOR LOOP to run just once. Remove the return statement at line 53 and it should work.

Let's me know if it works :)
Kofi A. JohnsonKofi A. Johnson
Hi briela,

At the same time, you have DMLs in the For Loop, and this code can hit the DML Limits, and make the code to crash.
I refactored a bit the code, to remove the DMLs inside the For Loop. I put some comments in the codes.
 
// ordersToUpsert will contains all the Orders to be upsert. 
            List<Order> ordersToUpsert = new List<Order>();
            // srcToInsert will contains all the Service_Request_Configuration__c to be upsert.
            List<Service_Request_Configuration__c> srcToInsert = new List<Service_Request_Configuration__c>();
            
            for(Asset asset: selectedAssets) {
                system.debug(asset);
                
                Service_Request_Configuration__c src = new Service_Request_Configuration__c ();
                
                src.Account__c = o.AccountId;
                src.Installed_Product_Asset__c = asset.Id;
                src.Installed_Product__c = asset.Product2Id;
                src.Order__c = o.id;
                
                //insert src; -- Removed this line because it is a DML in a For Loop, and replace by srcToInsert.add(src);
                srcToInsert.add(src);
                
                o.Service_Type__c = propPickValSelected;
                //upsert o; -- Removed this line because it is a DML in a For Loop, and replaced by ordersToUpsert
                ordersToUpsert.add(o);
                
                /* --Removed this PageReference and the return because it is in a For Loop. The return will stop the execution of the current method
                 * 
                 *PageReference pageRef = new PageReference('/apex/RMS_createServiceOrder4?id='+ o.Id + '&retUrl=' + o.Id);
                 *pageRef.setRedirect(true);
                 *return pageRef;
				 */
            }
            
            //-- Insert srcToInsert and orderToUpsert.
            insert srcToInsert;
            upsert ordersToUpsert;

 
ShivaKrishna(Freelancer)ShivaKrishna(Freelancer)
Hi there ,

Your code fine expect below three lines in method "processSelected"

  PageReference pageRef = new PageReference('/apex/RMS_createServiceOrder4?id='+ o.Id + '&retUrl=' + o.Id);
                pageRef.setRedirect(true);  ()
                return pageRef;


fist thing remove that return from for loop and place it outside
though you are creating the pagereference reference but at the end of the method you are returning null mean you are not using that as well. 
you are setting redirect to true (pageRef.setRedirect(true);  ) .. this is the real cause it makes all the parameters calculated to initial stage so that no records selected would be displayed.

I am not sure on your requirement. but this code may help you 

public PageReference processSelected() {
        PageReference pageRef = null;
        try{   
            List<Asset> selectedAssets = new List<Asset>();
             
            for(aAsset aAsst: getAssets()) {
                if(aAsst.selected == true) {
                    selectedAssets.add(aAsst.asset);
                }
            }
             
            System.debug('These are the selected Assets...');
            for(Asset asset: selectedAssets) {
                system.debug(asset);
                Service_Request_Configuration__c src = new Service_Request_Configuration__c ();
                src.Account__c = o.AccountId;
                src.Installed_Product_Asset__c = asset.Id;
                src.Installed_Product__c = asset.Product2Id;
                src.Order__c = o.id;
                insert src;
                o.Service_Type__c = propPickValSelected;
                upsert o;
            }
                pageRef = new PageReference('/apex/RMS_createServiceOrder4?id='+ o.Id + '&retUrl=' + o.Id);
                pageRef.setRedirect(true);  
        }
        catch(Exception ex){
            ApexPages.addMessages(ex);
        }
        return pageRef;
    }


use debug statement and for better back end debug.

let me know, if it helps you :)
nagasfdc1@gmail.com
 
This was selected as the best answer
brielea1984brielea1984
Thank you both! You both pointed out basically the same thing, and it was indeed something staring me right in the face :D This is why we should stop coding after 12 hours... 

Kofi yours worked fine, but Nagasudhakar's fit my use case more fully. Thank you both!
ShivaKrishna(Freelancer)ShivaKrishna(Freelancer)
@ brielea 

it happens when our eyes are crying to sleep :) . glad to hear that my post helped you.