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
Bob_zBob_z 

Visualforce page with update capabilities

I created a visualforce and a apex class to display junction object child records on an account page. It is working as expected, but i was wonder how can update my apex class to allow the junction object child records to be updated from the account page? I'm not sure how to accomplish this so i am reaching out to the community to see if anyone could help me update my class to support this function. My VF page and class is below.

VF Page:
<apex:page standardController="Account" extensions="VF_SiteServicePartnerLandController" lightningStylesheets="true"  >


<style>
       th{ width: 50%;}       
   </style>
 
    <apex:form > 
  


     <apex:pageBlock >
    
        
        <apex:pageBlockTable cellpadding="5" width="100%" columns="2" value="{!sspList}" var="item">
 
           <apex:column >
           <apex:outputField value="{!item.Supported_Trade__c}"/><br></br>
           <apex:outputLabel value=""><b>Service Partner Assigned to Site</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Partner Primary Contact</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Primary_Field_Contact__c}"/><br></br>
                <apex:outputLabel value=""><b>Primary Field  Cell</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Primary_Field_Mobile__c}"/><br></br>
                <apex:outputLabel value=""><b>Primary Field Email</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Primary_Field_Email__c}"/><br></br>
                <apex:outputLabel value=""><b>Secondary Contact</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Secondary_Field_Contact__c}"/><br></br>
                <apex:outputLabel value=""><b>Secondary Cell</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Secondary_Field_Mobile__c}"/><br></br>
                <apex:outputField value="{!item.Secondary_Field_Email__c}"/>
            
            </apex:column>
           
           
           <apex:column >
           
           <apex:outputLabel value=""><b>Service Partner Owner</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_Owner__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Partner Owner Cell</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_Owner_Mobile__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Partner Main Phone</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_Main_Phone__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Partner Owner Email</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_Owner_Email__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Provider Start Date</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_Start_Date__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Provider End Date</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_End_Date__c}"/>
            
            </apex:column>
            
      </apex:pageBlockTable>
   </apex:pageBlock>
 </apex:form>   
 </apex:page>

Apex Class:
// Used on the account page updated 1-31-2020
Public Class VF_SiteServicePartnerLandController{
   private Account acc;
   public List<Site_Service_Partner__c> sspList {get;set;}
   
   public VF_SiteServicePartnerLandController(ApexPages.StandardController sp){
       acc = (Account)sp.getRecord();
       sspList = new List<Site_Service_Partner__c>();
       sspList = [SELECT Id,Name,Site_Account__c,Primary_Field_Contact__c,Service_Partner__c,
                  Service_Partner_Owner__c,Service_Partner_Owner_Mobile__c,Service_Partner_Owner_Email__c,
                  Primary_Field_Email__c,Primary_Field_Mobile__c,Service_Partner_Site_Status__c, 
                  Contracted_Services__c,Secondary_Field_Contact__c,Secondary_Field_Email__c,Secondary_Field_Mobile__c,
                  Service_Partner_Start_Date__c,Service_Partner_End_Date__c,Service_Partner_Main_Phone__c,Trade__c,Supported_Trade__c  FROM Site_Service_Partner__c WHERE Site_Account__c =: acc.Id AND Site_Account__r.Trade__c includes('Land') AND Service_Partner_Site_Status__c = 'Active' ];

    
    Set<Id> bidId = new  Set<Id>();  
    for(Site_Service_Partner__c bs:sspList){
       bidId.add(bs.Id);
    }
     
   }

}

 
Best Answer chosen by Bob_z
Christan G 4Christan G 4
Hi Bob, I hope you are well. After researching more into this issue, it seems that Salesforce has limited DML capabilities within VF pages to increase security. It seems DML capabilities can only be used within <apex:components> with its allowDML attribute set to true. One can also specify an action within the <apex:page> to potentially invoke an action method to autocreate a record. In classic, you can potentially use Javascript buttons to perform DML actions. Please note that in Lightning, javascript buttons will no longer be supported so I am not sure if it would be worth the hassle in creating one.

Unfortunately, I don't think it is possible achieve what is it you wanted to do due to the extra security features that Salesforce has implemented. Even when I tried incorporating DML statements into a test VF page, it gave me the following error: System.LimitException: DML currently not allowed.

If anyone knows a potential workaround, please feel free to comment.

All Answers

itzmukeshy7itzmukeshy7
Use some action to submit the data changes and then in the apex do update sspList;
I guess this might be a way to do this.
Christan G 4Christan G 4
Hey Bob, I hope you are well. I am just now starting to learn Visualforce pages but I have a good amount of experience with Apex. Based on your question, I think you can create a method in your Apex class that does the following: 
 
  1. Capture the Account ID of that page by using ApexPages.currentPage().getParameters().get('id'); - You assign this to either an ID or String variable 
  2. Run a SOQL query that includes the fields you would like to update on the Account object and use WHERE clause to  filter the ID to equal the ID from #1. Assign this to an Account object variable.
  3. You can then assign the fields you want to change from the sspList to the Account object. I assume the list will only include one record based on your query so you can state sspList[0].Name = objAcc.Name as an example.
  4. After stating all the fields you like like to be updated, finally use update DML to update that account record.
  5. On the Visualforce page, create a commandbutton and assign its action attribute the name of the method you created. Example: {!updateAccount}. Name the button using value attribute. Ex. value="Update Account".
Apex Method Example:
public static void updateAccount() {
        
    String pgID = ApexPages.currentPage().getParameters().get('id');
    
    Account objAcc = [SELECT STATEFIELDS FROM Account WHERE ID =:pgId];
    
   //State all fields you want to update and assign their values
   objAcc.Name = sspList[0].Name;  
    
   //After stating all the fields, use DML update
   update objAcc;

 
Bob_zBob_z
Hi Christan,

Can i add your example to my exiasting class? Just not sure how to do that. 
Christan G 4Christan G 4
Hi Bob and sure. Please view the code below. Feel free to customize it. If you experience any issues when testing out the changes that I made, please feel free to inform me. I would be more than happy to assist.:

Apex Class:
// Used on the account page updated 1-31-2020
Public Class VF_SiteServicePartnerLandController{
   private Account acc;
   public List<Site_Service_Partner__c> sspList {get;set;}
   
   public VF_SiteServicePartnerLandController(ApexPages.StandardController sp){
       acc = (Account)sp.getRecord();
       sspList = new List<Site_Service_Partner__c>();
       sspList = [SELECT Id,Name,Site_Account__c,Primary_Field_Contact__c,Service_Partner__c,
                  Service_Partner_Owner__c,Service_Partner_Owner_Mobile__c,Service_Partner_Owner_Email__c,
                  Primary_Field_Email__c,Primary_Field_Mobile__c,Service_Partner_Site_Status__c, 
                  Contracted_Services__c,Secondary_Field_Contact__c,Secondary_Field_Email__c,Secondary_Field_Mobile__c,
                  Service_Partner_Start_Date__c,Service_Partner_End_Date__c,Service_Partner_Main_Phone__c,Trade__c,Supported_Trade__c  FROM Site_Service_Partner__c WHERE Site_Account__c =: acc.Id AND Site_Account__r.Trade__c includes('Land') AND Service_Partner_Site_Status__c = 'Active' ];

    
    Set<Id> bidId = new  Set<Id>();  
    for(Site_Service_Partner__c bs:sspList){
       bidId.add(bs.Id);
    }

   public static void updateAccount() { 
String pgID = ApexPages.currentPage().getParameters().get('id'); 
Account objAcc = [SELECT Name, STATE_OTHER_API_FIELDS_HERE FROM Account WHERE ID =:pgId]; 

//State all fields you want to update and assign their values 
objAcc.Name = sspList[0].Name; 

//After stating all the fields, use DML update that account record
update objAcc;
}
}
VF Page:
<apex:page standardController="Account" extensions="VF_SiteServicePartnerLandController" lightningStylesheets="true"  >


<style>
       th{ width: 50%;}       
   </style>
 
    <apex:form > 
     <apex:pageBlock >

        <!-- ADDITIONAL CODE: This is where I added the command button -->
        <apex:commandButton value="Update Account" onclick="{!updateAccount}" />

        <apex:pageBlockTable cellpadding="5" width="100%" columns="2" value="{!sspList}" var="item">
 
           <apex:column >
           <apex:outputField value="{!item.Supported_Trade__c}"/><br></br>
           <apex:outputLabel value=""><b>Service Partner Assigned to Site</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Partner Primary Contact</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Primary_Field_Contact__c}"/><br></br>
                <apex:outputLabel value=""><b>Primary Field  Cell</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Primary_Field_Mobile__c}"/><br></br>
                <apex:outputLabel value=""><b>Primary Field Email</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Primary_Field_Email__c}"/><br></br>
                <apex:outputLabel value=""><b>Secondary Contact</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Secondary_Field_Contact__c}"/><br></br>
                <apex:outputLabel value=""><b>Secondary Cell</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Secondary_Field_Mobile__c}"/><br></br>
                <apex:outputField value="{!item.Secondary_Field_Email__c}"/>
            
            </apex:column>
           
           
           <apex:column >
           
           <apex:outputLabel value=""><b>Service Partner Owner</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_Owner__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Partner Owner Cell</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_Owner_Mobile__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Partner Main Phone</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_Main_Phone__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Partner Owner Email</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_Owner_Email__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Provider Start Date</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_Start_Date__c}"/><br></br>
                <apex:outputLabel value=""><b>Service Provider End Date</b></apex:outputLabel><br></br>
                <apex:outputField value="{!item.Service_Partner_End_Date__c}"/>
            
            </apex:column>
            
      </apex:pageBlockTable>
   </apex:pageBlock>
 </apex:form>   
 </apex:page>
Bob_zBob_z
Hi Christan,

Thank you for helping. I apoligze for the delay.  I tried using the code provided and it  gave me a few errors. After updateing the code I am now gettingthe following error at line 21 Method must have a body.

 
// Used on the account page updated 1-31-2020
Public Class VF_SiteServicePartnerLandController{
   private Account acc;
   public List<Site_Service_Partner__c> sspList {get;set;}
   
   public VF_SiteServicePartnerLandController(ApexPages.StandardController sp){
       acc = (Account)sp.getRecord();
       sspList = new List<Site_Service_Partner__c>();
       sspList = [SELECT Id,Name,Site_Account__c,Primary_Field_Contact__c,Service_Partner__c,
                  Service_Partner_Owner__c,Service_Partner_Owner_Mobile__c,Service_Partner_Owner_Email__c,
                  Primary_Field_Email__c,Primary_Field_Mobile__c,Service_Partner_Site_Status__c, 
                  Contracted_Services__c,Secondary_Field_Contact__c,Secondary_Field_Email__c,Secondary_Field_Mobile__c,
                  Service_Partner_Start_Date__c,Service_Partner_End_Date__c,Service_Partner_Main_Phone__c,Trade__c,Supported_Trade__c  FROM Site_Service_Partner__c WHERE Site_Account__c =: acc.Id AND Site_Account__r.Trade__c includes('Land') AND Service_Partner_Site_Status__c = 'Active' ];

    
    Set<Id> bidId = new  Set<Id>();  
    for(Site_Service_Partner__c bs:sspList){
       bidId.add(bs.Id);
    }
   }
   public static void updateAccount(); { 
String pgID = ApexPages.currentPage().getParameters().get('id'); 
Account objAcc = [SELECT Name FROM Account WHERE ID =:pgId]; 

//State all fields you want to update and assign their values 
objAcc.Name = sspList[0].Name; 

//After stating all the fields, use DML update that account record
update objAcc;

}
}



 
Christan G 4Christan G 4
Hi Bob, I hope you are well. In code line 21, remove the ; after updateAccount(). I believe that should resolve your issue.
Christan G 4Christan G 4
As a follow up, one question I have is, is this VF page going to be apart of the Account page layout? If not, then I may have to make some adjustments to the code since it references the ID that is associated to the Account page being viewed at that time.
BobPBobP
The VF page is on the account page.
Christan G 4Christan G 4
Okay did, removing the colon resolve your issue or are you still having issues?
Bob_zBob_z
Also,

I did remove the : from updateAccount() and i now receive the folowing error. 

Error: Compile Error: Unexpected token 'public'. at line 21 column 4
Christan G 4Christan G 4
Okay I think it has something to do with the brackets. Delete the bracket above public, save and try again.
Bob_zBob_z
That didnt work unfortunately
Christan G 4Christan G 4
Sorry to hear. May I ask what error you received? I plan to do a mock up of this scenario within one of my dev orgs to see if I can achieve the functionality you wanted. I should have feedback by tomorrow the latest.
Christan G 4Christan G 4
Hi Bob, I hope you are well. After researching more into this issue, it seems that Salesforce has limited DML capabilities within VF pages to increase security. It seems DML capabilities can only be used within <apex:components> with its allowDML attribute set to true. One can also specify an action within the <apex:page> to potentially invoke an action method to autocreate a record. In classic, you can potentially use Javascript buttons to perform DML actions. Please note that in Lightning, javascript buttons will no longer be supported so I am not sure if it would be worth the hassle in creating one.

Unfortunately, I don't think it is possible achieve what is it you wanted to do due to the extra security features that Salesforce has implemented. Even when I tried incorporating DML statements into a test VF page, it gave me the following error: System.LimitException: DML currently not allowed.

If anyone knows a potential workaround, please feel free to comment.
This was selected as the best answer