1

In standard NewObj1__c page layout, I inserted a visualforce page that displays links of all related NewObj2__c records.

For example, in one NewObj1__c record, these are two related NewObj2__c links attached, named Test1 and Test2.

This works correctly.

However, there is a requirement wherein for each click per attached form is equivalent to some value.

Let's assume that first click per link, there's a score of 1. However, score should be equal to 0 if a link hasn't been clicked yet.

Click_Count__c field from NewObj1__c must be updated using this formula: Total Clicked Items/Total Count of attached links.

So if both Test1 and Test2 records are clicked, Click_Count__c must be equal to 1.

How can I do this without replacing outputlink tag with other tags? (commandbutton, commandlink, etc.)

Please take note that I've gotten the Total Count of attached links. The problem I've got is that Total_Clicked_Items__c does not update each time I click an attached link.

Apex Class:

public class NewController{

    public NewObj1__c newObj1 (public get; private set;)
    public List<NewObj2__c> newObj2List{get;set;}
    public List<NewObj2__c> newObj2List2{get;set;}
    public Id selectedObj2Id {get;set;}

    public NewController(ApexPages.StandardController stdController){
        this.newObj1 = (NewObj1__c)stdController.getRecord();

        this.newObj2List = new List<NewObj2__c>([SELECT Id, Name, NewObj1__c, Record_View_Count__c FROM NewObj2__c WHERE NewObj1__c =: newObj1.Id]);

        newObj2List2 = new List<Contact>();

        if(!newObj2List.isEmpty()){

            for(NewObj2__c o2 : newObj2List) {
                newObj2List2.add(new NewObj2__c(Id = o2.Id, Name = o2.Name, NewObj1__c = o2.NewObj1__c));    
            }
        }

    }

    public PageReference UpdateClickCount() {
        if(selectedObj2Id != null && selectedObj2Id != '') {
            UpdateNewObj1(selectedObj2Id);     
            return new PageReference('/' + selectedObj2Id);
        }
        else {
            return null;
        }

    }

    @future
    public static void UpdateNewObj1 (Id o2Id) {

        Id obj1Id;

        NewObj2__c newo2 = [SELECT Id, Name, NewObj1__c, Record_View_Count__c FROM NewObj2__c WHERE Id =: o2Id];

        obj1Id = newo2.NewObj1__c;

        NewObj1__c newo1 = [SELECT Id, Name, Total_Clicked_Items__c FROM NewObj1__c WHERE Id =: obj1Id];

        if(newo2.Record_View_Count__c == null) {
            newo1.Total_Clicked_Items__c = 1;
        }
        else {
            newo1.Total_Clicked_Items__c += 1;
        }

        update newo1; 
    }

}

Visualforce Page:

<apex:page standardController="NewObj1__c" extensions="NewController">
  <apex:form >
      <apex:outputText rendered="{!newObj2List == null}">No Records Found.</apex:outputText>
      <apex:pageBlock rendered="{!newObj2List != null}">
          <apex:actionFunction name="UpdateClicks" action="{!UpdateClickCount}" rerender="">
            <apex:param assignTo="{!selectedObj2Id}" value="" name="SelectedID" />
          </apex:actionFunction>
          <apex:pageBlockTable value="{!newObj2List2}" var="o2">
              <apex:column headerValue="Object 2">
                  <apex:outputLink value="#" onclick="UpdateClicks('{!o2.Id}');">{!o2.Name}</apex:outputLink>
              </apex:column>
          </apex:pageBlockTable><br/>         
      </apex:pageBlock>
  </apex:form>
</apex:page>

Image each time a link is clicked:

enter image description here

0

1 Answer 1

1

This is nearly a duplicate, since the root cause is the same. Heres the relevant bit from my other answer:

We create a action function, and set it to UpdateClickCount when the ouputLink is clicked. This actually doesn't work at all, unless you set the value attribute to an anchor (#). The page changes/refreshes before it can actually run the javascript & apex.

So instead of having the outputLink redirect the user, the onclick's action returns a PageReference with the contacts id. It also sets up a @future method to update the record in another context, instead of waiting for the dml to complete before redirecting the user.

Basically, you need to use this structure for your links, since the onclick action gets processed after the page is changed, causing your page state to be lost, along with your action.


Since you have a list of contacts, you need to pass along an id to the action in order to direct the user to the right record.

You'll need a Id variable to store the selected id in, and an action function outside of your iteration components. Create an apex:param with an empty value, which assigns the value passed to the javascript function to a controller variable.

<apex:param assignTo="{!SelectedContactId}" value="" name="SelectedID" />

Then, you set your onclick action to :

onclick="UpdateClicks('{!contact.Id}');"

By passing the id along to the apex:param under the actionFunction, you can direct the user to the correct record, while queueing up a @future method to update the click count.

Heres a full example:

Page:

<apex:page standardController="Account" extensions="OutputLinkController">  
    <apex:form>
        <apex:pageBlock>
          <apex:actionFunction name="UpdateClicks" action="{!UpdateClickCount}" reRender="">
              <apex:param assignTo="{!SelectedContactId}" value="" name="SelectedID" />
          </apex:actionFunction>
          <apex:pageBlockTable value="{!contacts}" var="contact">
              <apex:column headerValue="Contacts">
                  <apex:outputLink value="#" onclick="UpdateClicks('{!contact.Id}');">
                      {!contact.Name}
                  </apex:outputLink>
              </apex:column>
          </apex:pageBlockTable><br/>         
      </apex:pageBlock> 
    </apex:form>
</apex:page>

Controller:

public with sharing class OutputLinkController {
    public Account account { public get; private set; }
    
    public List<Contact> contacts { get; set; }
    
    public Id selectedContactId { get; set; }

    public OutputLinkController(ApexPages.StandardController controller) {
        this.account = (Account)controller.getRecord();
        
        this.contacts = new List<Contact>([
            SELECT Id, Name, Record_View_Count__c 
            FROM Contact 
            WHERE AccountId = :account.Id 
        ]);
    }
    
    public PageReference UpdateClickCount() {
        if (selectedContactId != null && selectedContactId != '') {
            UpdateContact(selectedContactId); 
            
            return new PageReference('/' + selectedContactId); 
        } else {
            return null; 
        }
    }

    @future 
    public static void UpdateContact(Id contactId) {
        Contact c = [SELECT Id, Record_View_Count__c FROM Contact WHERE Id = :contactId];

        if (c.Record_View_Count__c == null) {
            c.Record_View_Count__c = 1; 
        } else {
            c.Record_View_Count__c += 1;
        }

        update c; 
    }
}
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.