Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Friday, 6 May 2022

reRender Parent VF page data when Child VF page in pop-up window is getting closed.

OUTLINE 
While working on one of the requirements for a Health sector solutions customer based out in Atlanta, Georgia, there was a requirement to reRender Parent Visualforce page data when another Child Visualforce page in Pop-up window is getting closed. 

CHALLENGE 
Our main challenge was to call the JavaScript function in the Parent VF page from the child VF page in a pop-up window. 

APPROACH
  • Here the requirement was to open a VF page with the click of a button that creates a Contact record for a particular account, and after creating the contact record modify the contact table with the newly created contact.
  • To implement this requirement, we used custom JavaScript function and apex:actionFunction

REFERENCE CODE

ContactList.vfp
<apex:page Controller="ContactListController" lightningStylesheets="true">
    <apex:slds />
    
    <apex:form >
        <apex:commandbutton value="Add Contact"
                 oncomplete="window.open('/apex/AddContact?id={!accountId}', '_blank', 
                            'left=500, top=100, height=500px, width=500px');" />
        <br/><br/><br/>
        <apex:pageBlock id="ContactBlock">
            <apex:pageBlockTable value="{!contactList}" var="cnt" id="ContactList">
                <apex:column value="{!cnt.Name}"/>
                <apex:column value="{!cnt.phone}"/>
                <apex:column value="{!cnt.Email}"/>
            </apex:pageBlockTable>
        </apex:pageBlock>
        <apex:actionfunction name="reRenderContactListAF" 
                             action="{!retrieveContacts}" 
                             reRender="ContactBlock,ContactList" />
        
        <script>
        
        function reRenderContactList(){
            reRenderContactListAF();
        }
        </script>
    </apex:form>
</apex:page>

  • In the above code, we used custom JavaScript and actionFunction to retrieve the newly created contact and reRender the components.

AddContact.vfp
<apex:page Controller="ContactListController" lightningStylesheets="true">
    <apex:slds />
    
    <apex:form >
    	<apex:pageBlock title="Contact Form">           
        
        <apex:pageBlockSection columns="2">
            
            <apex:inputField value="{!newContact.FirstName}"/>
            <apex:inputField value="{!newContact.LastName}"/>
            <apex:inputField value="{!newContact.Email}"/>
            <apex:inputField value="{!newContact.Phone}"/>
            
        </apex:pageBlockSection>                       
        
        <apex:pageBlockButtons location="bottom">
            
            <apex:commandButton action="{!saveContact}" value="Save"
                         onclick="this.value='Saving ...';this.disabled=true"
                         oncomplete="this.value='Save';this.disabled=false;winClose()" />

        </apex:pageBlockButtons>
        
    </apex:pageBlock>
    <script>
    	function winClose(){
            window.opener.reRenderContactList();
            window.close();
    	}
    </script>
    </apex:form>
</apex:page>

  • In the above code, winClose() function will be executed on click of Save button. And winClose() JavaScript function will call the reRenderContactList() JavaScript function of the opener VF page. 

ContactListController.apxc
public class ContactListController {   
    
    public Contact newContact{get; set;} 
    public List<Contact> contactList{get; set;}
    public string accountId{get; set;}
    
    public ContactListController(){        
        accountId = ApexPages.CurrentPage().getParameters().get('id');                    
        newContact = new Contact(AccountId=accountId);
        retrieveContacts();
    }
    
    public void retrieveContacts(){
        contactList = [select Id, Name, Email, Phone 
                       from contact where AccountId=:accountId];
    }  
    
    public void saveContact(){ 
        upsert newContact;
    }
}


HOW IT WORKS  
  • So basically, whenever the save button gets clicked on VF page in the pop-up, it calls the JavaScript function winClose() and this function calls the JavaScript function of the Parent VF page.
  • JavaScript function of Parent VF page calls the apex:actionFunction which calls the controller method on its action attribute. 
  • After completion of controller method execution, apex:actionFunction rerenders some elements in the same component.

OUTPUT




CONCLUSION 

By using <apex:actionFunction> and JavaScript function effectively, we are able to reRender the contact table with the newly created contact. 

If you have any questions you can reach out our Salesforce Consulting team here.

Thursday, 24 February 2022

[Resolved:] Set value of the picklist field for the selected records to mass update in lightning web component.

SCENARIO 

While working on one of the requirements for a manufacturing sector solutions customer based out in Dallas, Texas there was a requirement to set selected value of picklist field to mass update of records in lightning web component.

CHALLENGE 

We have achieved this functionality of setting the value of picklist by creating  custom lightning web component. We have used custom javascript functions to update mass records. 

However, we got stuck with the issue of updating records for the selected value. 

APPROACH

To fulfill this requirement,we decided to create custom javascript functions to select multiple files and to assign values to each files. 

Below is a sample code for reference.

HTML Code:-

    <template>
      <lightning-card title="Account List"> 
        <div class="slds-m-around_medium" >

        
        <div class='slds-grid slds-gutters'>
          <div class='slds-col'>
            <lightning-input type="checkbox" onchange={handleSelectAllIndustryChk}
                             label="Select All" data-id="selectAllIndustry">
          </lightning-input>

          </div>
         </div>
         <template for:each={accounts} for:item="account" for:index="index">
          <div class='slds-grid slds-gutters' key={account.Name}>
            <div class='slds-col slds-m-top_large slds-size_1-of-7'>
              <lightning-input type="checkbox" name={account.Name} data-class="cus_IndustryHelper"
              onchange={handleIndustryCheckbox} data-id='IndustryTypeChk'>
              </lightning-input>
              </div>
              <div class='slds-col slds-size_3-of-7'>
                <lightning-input label="Account Name" type="text" value={account.Name}
                                  disabled="true">
                </lightning-input>
              </div>
              <div class='slds-col slds-size_3-of-7'>
                <lightning-combobox name={account.Name} label="Industry" data-id={account.Name}
                                    class="picklistContent"  dropdown-alignment="auto"
                                    placeholder="Select account Type" options={IndustryPicklist.data.values}
                                    onchange={handleIndustrySelectionChange} required>
                </lightning-combobox>
              </div>
          </div>
        </template>
      </div>
      </lightning-card>  
    </template>    
  

JavaScript Code:-

import { LightningElement, api, wire, track } from 'lwc';
import AccountList from '@salesforce/apex/AccountController.AccountList';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import Account_OBJECT from '@salesforce/schema/Account';
import Industry_FIELD from '@salesforce/schema/Account.Industry';
   
export default class DataTableInLwc extends LightningElement {
    
    @track accounts=[];
    @track selectedIndustryValues=[];
    
    

  @wire(AccountList)
  wiredfiles(result){
      
      if(result.data){
          this.accounts=result.data;
          
      }
      else{
          console.log('Data not found');
      }
    }


    @wire(getObjectInfo, { objectApiName: Account_OBJECT })

    AccountMetadata;

    @wire(getPicklistValues,

        {

            recordTypeId: '$AccountMetadata.data.defaultRecordTypeId',

            fieldApiName: Industry_FIELD

        }

    )

    IndustryPicklist;
    
   

    handleSelectAllIndustryChk(event) {
    this.selectedIndustryValues = [];
    var checkboxes = this.template.querySelectorAll('[data-id="IndustryTypeChk"]');
    for (var i = 0; i < checkboxes.length; i++) {
        checkboxes[i].checked = event.target.checked;
        event.target.checked ? this.selectedIndustryValues.push(checkboxes[i].name) : '';
        }
    }

        
        handleIndustryCheckbox(event) {
            if (event.target.checked) {
                this.selectedIndustryValues.push(event.target.name);
                let checkboxes = this.template.querySelectorAll('[data-class="cus_IndustryHelper"]');
                let length = 0;
                for (var i = 0; i < checkboxes.length; i++) {
                    (checkboxes[i].checked == true) ? length = length + 1: length = length - 1;
                }
                ((checkboxes.length) == length) ? this.template.querySelectorAll('[data-id="selectAllIndustry"]')[0].checked = true: this.template.querySelectorAll('[data-id="selectAllIndustry"]')[0].checked = false;
            } else {
                this.selectedIndustryValues.splice(this.selectedIndustryValues.indexOf(event.target.name), 1);
                this.template.querySelectorAll('[data-id="selectAllIndustry"]')[0].checked = false;
                length -= 1;
            }
        }
            
        handleIndustrySelectionChange(event)
        {
            if (this.selectedIndustryValues.indexOf(event.target.name) != -1) {
                for (var i = 0; i < this.selectedIndustryValues.length; i++) {
                var selected = this.template.querySelectorAll('[data-id="' + this.selectedIndustryValues[i] + '"]')[0];
                selected.value = event.target.value;
                   }
                }
        }



}  


  • handleSelectAllIndustryChk:- By clicking select all checkbox it will check all the checkboxes.
  • handleIndustryCheckbox:- Checks for checkboxes to see whether it is selected or
    
    unselected.
  • handleIndustrySelectionChange:- Used when value is selected from the picklist 
    
    and assigns that value to each and every selected picklist.

Apex Class:-

public with sharing class AccountController {
    @AuraEnabled(cacheable=true)
    public static List<Account> AccountList() {
        return [SELECT Id, Name ,Industry FROM Account LIMIT 5 ];
    }
}

OUTPUT:-




CONCLUSION
 
By using above mentioned javascript functions, We are able to set selected value of picklist field based for bulk/mass update records in lightning web component.

If you have any questions you can reach out our Salesforce Consulting team here.

Thursday, 6 January 2022

[Resolved:] Set default value to dependent picklist based on the value selected on controlling picklist in VF page

SCENARIO 

While working on one of the requirements for a health sector solutions customer based out Atlanta, Georgia there was a requirement to assign default value to particular dependent picklist field based on value selected on controlling picklist field in VF page.

 
CHALLENGE 

Although, We can achieve the requirement by making the field mandatory on page layout but  the client doesn't want that field to be required. So we have made custom JS to set default value to dependent picklist based on controlling picklist field value in the VF page.


RESOLUTION 

To fulfil the requirement, we have used <apex:actionFuntion> tag of visualforce page. By using this tag, we can call apex controller method from Javascript code  using  an  AJAX  request.   

Below is a sample code for reference. Here, we get the value of controlling picklist field and calling apex class using <apex:actionFunction>

ActionFunctionVFPage.vfp
<apex:page controller="retrieveValue">
    <script>
    function changefield(regionValue){
        
        var r =document.getElementById(regionValue);
        
        if(regionValue == "India"){            
            rerendAction();
        }
    }
    </script>
    <apex:form >
        <apex:sectionHeader title="Account" subtitle="Region Picklist Value"/>
        <apex:actionFunction action="{!zoneValue}" name="rerendAction" rerender="zone"/>
        <apex:pageblock id="pageRender">
            
            <apex:pageblocksection >
                
                <apex:pageblocksectionitem >
                    
                    <apex:outputlabel value="Region"/>
                    
                    <apex:inputField value="{!acc.Region__c}" onchange="changefield(this.value)"/>
                </apex:pageblocksectionitem>
                
            </apex:pageblocksection>
            
            <apex:pageblocksection id="zonefield">
                
                <apex:pageblocksectionitem >
                    <apex:outputlabel value="Zone"/>
                    <apex:inputField value="{!acc.Zone__c}" id="zone"/>
                    
                </apex:pageblocksectionitem>
                
            </apex:pageblocksection>
        </apex:pageblock>
        
    </apex:form>
    
</apex:page>

ActionFunctionController.apxc
global class retrieveValue {
    public Account acc{get;set;}
    public retrieveValue(){
        acc=new Account();
    }
  
    public void zoneValue()
    {
         acc.Zone__c = 'West_Zone';
    }
    
}

In apex class, we are setting default values to dependent picklist and action function will reRender the dependent picklist field.
                           
Output


CONCLUSION 

By Using custom JS and <apex:actionFuntion> , we are able to set default value to dependent picklist field based on value selected on controlling picklist field in VF page. 

If you have any questions you can reach out our Salesforce Consulting team here.

Thursday, 11 November 2021

[Resolved:] File Upload using REST API from Salesforce to SharePoint with special characters in filename.


SCENARIO

While working on one of the requirements for a packaging solutions customer based out Atlanta, Georgia there was a requirement to allow Salesforce users to upload documents from Salesforce entities.


Due to Salesforce storage limitation, uploaded documents are stored into SharePoint.


CHALLENGE

We have achieved functionality of uploading a file from Salesforce to SharePoint by creating custom lightning web component. We have used SharePoint REST APIs for direct upload from Salesforce to SharePoint.

However, we got stuck with the error while uploading a file contains special characters. 


RESOLUTION

We tried various solutions to resolve the issue but no luck. After relentless efforts, we concluded to utilize simple JavaScript function which encodes given file name and upload to SharePoint with the same name through REST APIs. Finally, it does the trick. Below is the sample for the same:


var updatedFileName = encodeURIComponent(this.files.name);
var url1 = 'https://br.sharepoint.com/sites/SFUpload' + "/_api/web/GetFolderByServerRelativePath('/Sites//SFUpload/Document Library')/Files/AddUsingPath(overwrite=true,decodedurl='" + updatedFileName + "')";


CONCLUSION

By encoding the file name, we are successfully able to upload a file with special characters from Salesforce to SharePoint.


If you have any questions you can reach out our Salesforce Consulting team here.

Thursday, 10 June 2021

How to use apex:actionFunction in a Salesforce Visualforce Page?


SCENARIO


While working on one of the requirements for a banking sector project for a customer based in San Diego, California there was a requirement to update selected record in Visual Force Page.

 

Clicking on Update button, we need to pass the updated values from inputs of Visualforce page to apex class so that is that DML operations can be performed.

 

SOLUTION


To fulfil the requirement, we have used <apex:actionFuntion> tag of Visualforce page. By using this tag, we can call apex controller method from java script code using an AJAX request.  


To set field values directly from VF page, we have used <apex:param> with <apex:actionFunction> and added this keyword in the assignedTo attribute of <apex:param>. 

 

Below is a sample code for reference. Here we are updating Account Name using <apex:actionFunction>.

  1. On click of Update button, JS function will get the updated value of Account Name and pass it to the param of actionFunction. 
  2. The actionFunction first sets the value of the variable and then invokes the method of apex class to update the account record. 

ActionFunction.vfp 

<apex:page controller="actionFunctionExampleController" sidebar="false" showHeader="false">
    <div style="margin : 20px;">
        
        <apex:form id="accountForm">
            <apex:actionFunction action="{!updateAccount}" name="updateAccountAF" reRender="dataTable">
                <apex:param name="accountName" assignTo="{!this.account.Name}" value="" />
            </apex:actionFunction>
            
            <apex:outputpanel >
                <label>Name :</label>
                <apex:inputField id="accountName" value="{!account.Name}"/>
                <apex:commandButton value="Update" onclick="GetAccountName(); return false;" />
            </apex:outputpanel>
        </apex:form>
        
        <div style="margin:20px 0px;">
            <apex:dataTable value="{!account}" var="acc" id="dataTable" border="1" width="50%">
                <apex:column value="{!acc.Name}" headerValue="Name"/>
                <apex:column value="{!acc.Type}" headerValue="Type"/>
                <apex:column value="{!acc.AccountNumber}" headerValue="Account Number"/>            
                <apex:column value="{!acc.Industry}" headerValue="Industry"/>
            </apex:dataTable>
        </div>
    </div>
    
    <script type="text/javascript">
        function GetAccountName(){
            var accountName = document.getElementById("{!$Component.accountForm.accountName}").value;        
            updateAccountAF(accountName);
        }
    </script>
    
</apex:page>


ActionFunctionController.apxc 

public class actionFunctionExampleController {
    
    public Account account {get;set;}
        
    public actionFunctionExampleController(){
        Id accountId  = ApexPages.CurrentPage().getparameters().get('id');
        account = [select id, Name, AccountNumber, Type, Industry from Account where id =: accountId ];
    }
    
    public void updateAccount(){
        update account;
    }
}


NOTE: 


Also, we can get the values of <apex:param> by using the below code in apex class. For that, we don't need to write assignedTo attribute in VF page. 


Apexpages.currentPage().getParameters.get(paramName);



FACTS TO CONSIDER:

  • An <apex:actionFunction> component must be a child of an <apex:form> component.
  • Since the caller and <apex:actionFunction> are bound based on parameter order, make sure the caller's argument list matches the order of <apex:param>. 
  • For API version 23 or later, you cannot use <apex:actionFunction> inside an iteration component like, <apex:pageBlockTable>, <apex:repeat>, and so on. 

 

OUTPUT



If you have any questions you can reach out our Salesforce Consulting team here.