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
Nick ValerioteNick Valeriote 

Sample code with AddButton element

Hi SF Community,

I'm not a developer,  but have dabled in some code in the past.  

Wondering if anyone has some sample code I can modify/use to achieve the following (see screen shot below)?  I don't need those specific field headings, as I would substitute them with other field headings.  And I'm hoping to have that Add Row button, whereby when a user clicks it, it adds a new row.  I want to add this as a new section on the page layour of our opportunity page.

User-added image

Does anyone have some code I can use for such a thing?
Thanks much!
Nick

 

Best Answer chosen by Nick Valeriote
Khan AnasKhan Anas (Salesforce Developers) 
Hi Nick,

Sorry for the late reply. Please use below code to save records to associate Opportunity. I created a lookup relationship field in my custom sObject with API name Opportunity__c to relate custom object with opportunity.

Custom sObject: Student__c
Lookup in Student__c related to Opportunity: Opportunity__c
 
public class GroupInsertController{
    
    public List<Student__c> studentAddList {get;set;}
    public List<Student__c> stu {get; set;}
    public ApexPages.StandardController stdController;
    public ID oppId;
    
    public GroupInsertController(ApexPages.StandardController stdController)
    {
        this.stdController = stdController;
        oppId=stdController.getId();
        student__c s = new student__c();
        studentAddList = new List<Student__c>();
        stu = new List<Student__c>();
        studentAddList.add(s);
    }
    
    public void addRow()
    {
        student__c s1 = new student__c();
        studentAddList.add(s1);
    }
    
    public void delRow()
    {
        Integer i=studentAddList.size();
        studentAddList.remove(i-1);
    }
    
    public PageReference groupInsert(){
        try{
            for(Student__c s2 : studentAddList){
                s2.Opportunity__c = oppId;
                stu.add(s2);
            }
            insert stu;
        }
        catch (Exception e) {
            ApexPages.addMessages (e);
        }
        PageReference pr = new PageReference(System.currentPageReference().getURL());
        pr.setRedirect(true);
        return null;
    }
}

After that, you can create a related list of your object in Opportunity layout so that related records will be visible on Opportunity detail page.


I hope it helps you.

Kindly mark this as solved if the information was helpful.

Regards,
Khan Anas

All Answers

Khan AnasKhan Anas (Salesforce Developers) 
Hi Nick,

I trust you are doing very well.

Below is the sample code which I have tested in my org and it is working fine. Kindly modify the code as per your requirement.

Visualforce:
<apex:page controller="GroupInsertController" >
    <apex:form >        
        <apex:pageBlock >             
        <apex:pageblockSection >
            <apex:pageBlockTable value="{!studentAddList}" var="std">
                <apex:column headerValue="Student Name">
                    <apex:inputField value="{!std.Name}"/>
                </apex:column>
                <apex:column headerValue="Course">
                    <apex:inputField value="{!std.Course__c}"/>
                </apex:column>
                <apex:column headerValue="Mobile Number">
                    <apex:inputField value="{!std.Mobile_Number__c}"/>
                </apex:column>
            </apex:pageBlockTable> 
            <br/><apex:commandLink value="Add Row" action="{!addRow}"/> 
            <br/><apex:commandLink value="Remove Row" action="{!delRow}"/>       
        </apex:pageblockSection>        
        <apex:pageblockButtons >
                <apex:commandButton value="Save" action="{!groupInsert}" />
        </apex:pageblockButtons>
    </apex:pageBlock>
</apex:form>
</apex:page>

Controller:
public class GroupInsertController{
    
    public List<Student__c> studentAddList {get;set;}
    public List<Student__c> stu {get; set;}
     
    public GroupInsertController()
    {
        student__c s = new student__c();
        studentAddList = new List<Student__c>();
        stu = new List<Student__c>();
        studentAddList.add(s);
    }
    
    public void addRow()
    {
        student__c s1 = new student__c();
        studentAddList.add(s1);
    }
    
    public void delRow()
    {
        Integer i=studentAddList.size();
        studentAddList.remove(i-1);
    }
    
    public PageReference groupInsert(){
         try{
             for(Student__c s2 : studentAddList){
                if(s2.course__c == 'Salesforce'){
                    stu.add(s2);
                }
             }
             insert stu;
         }
         catch (Exception e) {
             ApexPages.addMessages (e);
         }
        PageReference pr = new PageReference(System.currentPageReference().getURL());
        pr.setRedirect(true);
        return pr;
    }
}

Screenshot:
User-added image


Instead of commandLink you can use commandButton if you want button on your page.


I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in future.

Thanks and Regards,
Khan Anas
Nick ValerioteNick Valeriote
Thanks so much, Khan!  I'll give it a try and let you know how it goes!
Nick ValerioteNick Valeriote
Hi Khan -
Question - is 'Student__c' referencing a custom object in your example?  Can I replace this with Opportunity?
Khan AnasKhan Anas (Salesforce Developers) 
Hi Nick,

Yes, you can replace Student__c with Opportunity :)
Sorry, I forgot to mention, Student__c is a custom object.
Name, Course__c (Picklist Field), Mobile_Number__c are fields of Student__c object.
Nick ValerioteNick Valeriote
Thanks :)  I shall try it out.
Nick ValerioteNick Valeriote

Another quick question for you, Khan...
What is function of this part of the code:

"public PageReference groupInsert(){
         try{
             for(Opportunity s2 : OpportunityAddList){
                if(s2.course__c == 'Salesforce'){
                    stu.add(s2);
                }
             }
             insert stu;
         }

Khan AnasKhan Anas (Salesforce Developers) 
I have used groupInsert function to Insert the records which user has entered. Only those records will be inserted whose course value is 'Salesforce'. You can skip if condition. If you want to insert the records you can use below code:

public PageReference groupInsert(){
         try{
             for(Student__c s2 : studentAddList){
                stu.add(s2);
             }
             insert stu;
         }
         catch (Exception e) {
             ApexPages.addMessages (e);
         }
        PageReference pr = new PageReference(System.currentPageReference().getURL());
        pr.setRedirect(true);
        return pr;
    }
Khan AnasKhan Anas (Salesforce Developers) 
Hi Nick,

Don't forget to mark this as solved if it's resolved so that it gets removed from the unanswered queue which results in helping others who are encountering a similar issue.

Regards,
Khan Anas
Nick ValerioteNick Valeriote
Grrrreat!  
This is what I wanted, looks good, thanks!!!
However, do you know how I can add this as a section to the Opportunity page layout?  I don't see it there as an option...
User-added image
Khan AnasKhan Anas (Salesforce Developers) 
Nick,

To embed a Visualforce page into page layout, the Visualforce page should be using the standard controller tag referencing the same entity that will be used in the page layout.
 
<apex:page standardController="Opportunity" extensions="ApexClass">
     Your Code
</apex:page>

I hope it helps you.

Regards,
Khan Anas
Nick ValerioteNick Valeriote
Thanks, Khan.  Does that mean I need to update the controller?  I'm now no longer referencing <apex:page controller="GroupInsertController" > in my visualforce page.  It's now telling me to "Create Apex class 'public with sharing class ApexClass'"
 
Nick ValerioteNick Valeriote
Here's what I have so far, in case that helps identify my issue...

Current error on Vforce page: Error: Unknown property 'OpportunityStandardController.OpportunityAddList'

Vforce page code:
<apex:page standardController="Opportunity" extensions="ApexClass">
    <apex:form >       
        <apex:pageBlock >            
        <apex:pageblockSection >
            <apex:pageBlockTable value="{!OpportunityAddList}" var="std">
                <apex:column headerValue="SOW Item">
                    <apex:inputField value="{!std.SOW_Item__c}"/>
                </apex:column>
                <apex:column headerValue="SOW Hours">
                    <apex:inputField value="{!std.SOW_Hours__c}"/>
                </apex:column>
                <apex:column headerValue="SOW Item Cost">
                    <apex:inputField value="{!std.SOW_Item_Cost__c}"/>
                </apex:column>
            </apex:pageBlockTable>
            <br/><apex:commandLink value="Add Row" action="{!addRow}"/>
            <br/><apex:commandLink value="Remove Row" action="{!delRow}"/>      
        </apex:pageblockSection>       
        <apex:pageblockButtons >
                <apex:commandButton value="Save" action="{!groupInsert}" />
        </apex:pageblockButtons>
    </apex:pageBlock>
</apex:form>
</apex:page>


Class:
public class GroupInsertController{
    
    public List<Opportunity> OpportunityAddList {get;set;}
    public List<Opportunity> opp {get; set;}
     
    public GroupInsertController()
    {
        Opportunity s = new Opportunity();
        OpportunityAddList = new List<Opportunity>();
        opp = new List<Opportunity>();
        OpportunityAddList.add(s);
    }
    
    public void addRow()
    {
        Opportunity s1 = new Opportunity();
        OpportunityAddList.add(s1);
    }
    
    public void delRow()
    {
        Integer i=OpportunityAddList.size();
        OpportunityAddList.remove(i-1);
    }
    
    public PageReference groupInsert(){
         try{
             for(Opportunity s2 : OpportunityAddList){
                opp.add(s2);
             }
             insert opp;
         }
         catch (Exception e) {
             ApexPages.addMessages (e);
         }
        PageReference pr = new PageReference(System.currentPageReference().getURL());
        pr.setRedirect(true);
        return pr;
    }
    }
Khan AnasKhan Anas (Salesforce Developers) 
Hi Nick,

Please refer to below code:

Visualforce:
<apex:page standardController="Opportunity" extensions="GroupInsertController">
    <apex:form >       
        <apex:pageBlock >            
            <apex:pageblockSection >
                <apex:pageBlockTable value="{!OpportunityAddList}" var="std">
                    <apex:column headerValue="SOW Item">
                        <apex:inputField value="{!std.SOW_Item__c}"/>
                    </apex:column>
                    <apex:column headerValue="SOW Hours">
                        <apex:inputField value="{!std.SOW_Hours__c}"/>
                    </apex:column>
                    <apex:column headerValue="SOW Item Cost">
                        <apex:inputField value="{!std.SOW_Item_Cost__c}"/>
                    </apex:column>
                </apex:pageBlockTable>
                <br/><apex:commandLink value="Add Row" action="{!addRow}"/>
                <br/><apex:commandLink value="Remove Row" action="{!delRow}"/>      
            </apex:pageblockSection>       
            <apex:pageblockButtons >
                <apex:commandButton value="Save" action="{!groupInsert}" />
            </apex:pageblockButtons>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Controller:
public class GroupInsertController{
    
    public List<Opportunity> OpportunityAddList {get;set;}
    public List<Opportunity> opp {get; set;}
    
    public GroupInsertController(ApexPages.StandardController stdController)
    {
        Opportunity s = new Opportunity();
        OpportunityAddList = new List<Opportunity>();
        opp = new List<Opportunity>();
        OpportunityAddList.add(s);
    }
    
    public void addRow()
    {
        Opportunity s1 = new Opportunity();
        OpportunityAddList.add(s1);
    }
    
    public void delRow()
    {
        Integer i=OpportunityAddList.size();
        OpportunityAddList.remove(i-1);
    }
    
    public PageReference groupInsert(){
        try{
            for(Opportunity s2 : OpportunityAddList){
                opp.add(s2);
            }
            insert opp;
        }
        catch (Exception e) {
            ApexPages.addMessages (e);
        }
        PageReference pr = new PageReference(System.currentPageReference().getURL());
        pr.setRedirect(true);
        return pr;
    }
}

Kindly mark this as solved if the information was helpful.

Regards,
Khan Anas
Nick ValerioteNick Valeriote
Yes!  That's it.  Thanks, Khan.
Looking good on the Opportunity page.  However, when I enter values in these fields and click the Save button, the values disappear.  How can I save inputted values and have them associated to the opportunity record I'm on?
User-added image
Nick ValerioteNick Valeriote
Thanks so much for your help on this, Khan.  Any chance you can advise on why the data inputted to the fields in the code are not saving to the associated Opportunity record?
Nick ValerioteNick Valeriote
Hi Khan.  I'm sure you're busy, and can appreciate that.  I'm so close to completing this piece of functionality, but just need the last bit of information from you on how to save data inputted in these new fields to the opportunity record.  If it's too difficult to provide an answer for, just let me know.  Thanks much!
Khan AnasKhan Anas (Salesforce Developers) 
Hi Nick,

Sorry for the late reply. Please use below code to save records to associate Opportunity. I created a lookup relationship field in my custom sObject with API name Opportunity__c to relate custom object with opportunity.

Custom sObject: Student__c
Lookup in Student__c related to Opportunity: Opportunity__c
 
public class GroupInsertController{
    
    public List<Student__c> studentAddList {get;set;}
    public List<Student__c> stu {get; set;}
    public ApexPages.StandardController stdController;
    public ID oppId;
    
    public GroupInsertController(ApexPages.StandardController stdController)
    {
        this.stdController = stdController;
        oppId=stdController.getId();
        student__c s = new student__c();
        studentAddList = new List<Student__c>();
        stu = new List<Student__c>();
        studentAddList.add(s);
    }
    
    public void addRow()
    {
        student__c s1 = new student__c();
        studentAddList.add(s1);
    }
    
    public void delRow()
    {
        Integer i=studentAddList.size();
        studentAddList.remove(i-1);
    }
    
    public PageReference groupInsert(){
        try{
            for(Student__c s2 : studentAddList){
                s2.Opportunity__c = oppId;
                stu.add(s2);
            }
            insert stu;
        }
        catch (Exception e) {
            ApexPages.addMessages (e);
        }
        PageReference pr = new PageReference(System.currentPageReference().getURL());
        pr.setRedirect(true);
        return null;
    }
}

After that, you can create a related list of your object in Opportunity layout so that related records will be visible on Opportunity detail page.


I hope it helps you.

Kindly mark this as solved if the information was helpful.

Regards,
Khan Anas
This was selected as the best answer
Nick ValerioteNick Valeriote
Thanks so much, Khan!  Super help!  That worked.
 
Nick ValerioteNick Valeriote
Any chance you know how to create a test class so I can move this to production and validate it in the change set?  ;)  Might be asking too much, I get it.
Khan AnasKhan Anas (Salesforce Developers) 
Nick,

It's my pleasure. I’m glad I was able to help!

Below is my test class with 100% code coverage.

Controller:
public class GroupInsertController{
    
    public List<Student__c> studentAddList {get;set;}
    public List<Student__c> stu {get; set;}
    public ApexPages.StandardController stdController;
    public ID oppId;
    
    public GroupInsertController(ApexPages.StandardController stdController)
    {
        this.stdController = stdController;
        oppId=stdController.getId();
        student__c s = new student__c();
        studentAddList = new List<Student__c>();
        stu = new List<Student__c>();
        studentAddList.add(s);
    }
    
    public void addRow()
    {
        student__c s1 = new student__c();
        studentAddList.add(s1);
    }
    
    public void delRow()
    {
        Integer i=studentAddList.size();
        studentAddList.remove(i-1);
    }
    
    public PageReference groupInsert(){
        try{
            for(Student__c s2 : studentAddList){
                s2.Opportunity__c = oppId;
                stu.add(s2);
            }
            insert stu;
        }
        catch (Exception e) {
            ApexPages.addMessages (e);
        }
        return null;
    }
}

Test Class:
@isTest
public class GroupInsertTest {
    
    static testMethod void myUnitTest() {
        
        Opportunity testOpp = new Opportunity(); //Insert Opp
        testOpp.Name='Test Opp';
        testOpp.StageName='Qualification';
        testOpp.CloseDate=System.Today()+30;
        insert testOpp;
        
        Student__c cont = new Student__c(); //Insert Student
        cont.Name ='Test';
        cont.Course__c ='Salesforce';
        cont.Mobile_Number__c='9999999999';
        cont.Opportunity__c =testOpp.id; //Related Opportunity
        insert cont;
        
        ApexPages.StandardController sc = new ApexPages.StandardController(cont);
        GroupInsertController contactextObj = new GroupInsertController(sc);
        
        contactextObj.addRow();  
        contactextObj.delRow();
        contactextObj.groupInsert();
    }
}


Regards,
Khan Anas
Nick ValerioteNick Valeriote
Thanks for this, Khan!
I updated the test class so it fits with my items (not your custom Students stuff).  However, when I validate this test class on the incominging Change Set in production, I get this error:
"System.NullPointerException: Argument 1 cannot be null 
Stack Trace: Class.SOWItemsOpp2.groupInsert: line 41, column 1 Class.SOWItemsOpp2Test.myUnitTest: line 24, column 1".


Here's my updated test class code:
@isTest
public class SOWItemsOpp2Test {
     
    static testMethod void myUnitTest() {
         
        Opportunity testOpp = new Opportunity(); //Insert Opp
        testOpp.Name='Test Opp';
        testOpp.StageName='Quote/SOW';
        testOpp.CloseDate=System.Today()+30;
        insert testOpp;
         
        SOW_Types__c cont = new SOW_Types__c(); //Insert Sow Types
        cont.SOW_Item__c ='Project Management';
        cont.SOW_Hours__c=99;
        cont.SOW_Item_Cost__c=1255;
        cont.Opportunity__c =testOpp.id; //Related Opportunity
        insert cont;
         
        ApexPages.StandardController sc = new ApexPages.StandardController(cont);
        SOWItemsOpp2 contactextObj = new SOWItemsOpp2(sc);
         
        contactextObj.addRow(); 
        contactextObj.delRow();
        contactextObj.groupInsert();
    }
}


Any idea what the issue  might be?
Thanks.

Nick

Khan AnasKhan Anas (Salesforce Developers) 
Nick, 

Please update controller code, you need to remove 2 lines from groupInsert method. 

PageReference pr = new PageReference(System.currentPageReference().getURL()); pr.setRedirect(true);

Remove this and you are good to go :) 

Regards, 
Khan Anas
Nick ValerioteNick Valeriote
Khan, once again, thank you.  That worked.  I'm all set.  I really do appreciate your support with this, and timely response.  All the best.  Nick