0

I'm working on a vf page that was developed last year by a developer who's no longer here. The page is a custom contact related list that displays Contacts related to the Account but with more features to it. It was half finished in that there is functionality to toggle contacts that are inactive both in the vf page and the controller's query. However, there is no triggering mechanism to force the action to toggle.

Thus, I want to be able to click on an outputlink on the page, have it render the page and pass a variable through a get;set; to the controller. The controller is already setup I just need help to pass the value over.

I have this code snipit that I am working with:

<apex:actionFunction action="{!delContactRecord}" name="delContactAF" rerender="frm" status="counterStatus">
        <apex:param name="contactId" value="" assignTo="{!idSelectedContactId}"/>
    </apex:actionFunction>
    <apex:actionFunction action="{!toggleInactive}" name="toggleInactive" rerender="frm" status="counterStatus">
    </apex:actionFunction>
    <apex:outputpanel rendered="{!!isCorporateAccount}" >
        <a href="{!newContactUrl}" target="_top" style="margin:4px">New Contact</a>
        <a href="{!mergeContactUrl}" target="_top" style="margin:4px">Merge Contact</a>
        <a href="/003?id={!currentAccount.Id}&rlid=RelatedContactList" target="_top" style="margin:4px">View All Contacts</a>
        <a href="{!showInactiveContacts}" target="_top" style="margin:4px"> Toggle Inactive Contacts</a>
    </apex:outputpanel>
    <apex:outputLink value="{!toggleInactive}"> Toggle </apex:outputLink>
    <div style="margin-bottom:10px;" />
    <div class="se-pre-con"/>
    <div style="height:400px;overflow:auto;">

        <table id="contactTableID" class="display" cellspacing="0" width="100%">
            <thead style="background-color:#F5F5F5">
                <tr>
                    <th style="background-image:none;"></th>
                    <th style="background-image:none;"></th>
                    <th>Name</th>
                    <th>Practice</th>
                    <apex:repeat value="{!$ObjectType.Contact.FieldSets.SL_EnhancedContact}" var="fs">
                    <th>
                        {!fs.Label}
                    </th>
                    </apex:repeat>
                </tr>
            </thead>
             <tbody>
                <apex:repeat value="{!mapContactIdToContactWrapper}" var="key">
                <tr>
                    <td>
                        <a href="/{!mapContactIdToContactWrapper[key].objContact.Id}/e" target="_top" style="margin:4px">Edit</a>
                    </td>
                    <td>
                        <apex:outputLink value="javascript:if (window.confirm('Are you sure?')) delContactAF('{!mapContactIdToContactWrapper[key].objContact.id}');"> Del
                        </apex:outputLink>
                    </td>
                    <td>
                        <a href="/{!mapContactIdToContactWrapper[key].objContact.Id}" target="_top">
                            <apex:outputText value="{!mapContactIdToContactWrapper[key].objContact.Name}"/>
                        </a>
                    </td>
                    <td>
                        <apex:outputText value="{!mapContactIdToContactWrapper[key].strName}"/>
                    </td>
                    <apex:repeat value="{!$ObjectType.Contact.FieldSets.SL_EnhancedContact}" var="fs">
                    <td class="tdClass">
                        <apex:outputField value="{!mapContactIdToContactWrapper[key].objContact[fs]}">
                        </apex:outputField>
                    </td>
                    </apex:repeat>
                </tr>
               </apex:repeat>
            </tbody>
        </table>
    </div>

There is a bit in there with "delContactAF" that is a link that you click that deletes a contact record and refreshes the page. It works so I tried to mimic that but with no success.

Can you see where I'm going wrong?

EDIT:

I believe that my requirement is when I open the vf page a value should be false. Right now it's being set in the controller. When I click a button or link in the vf page I want to set the value to be true. This would get passed to the controller which would change the query. Finally the vf page would refresh to display the records from the query.

Controller Code:

public with sharing class EnhancedContactRelatedListCtrl 
{
/* Start - Variables */
public Map<Id, ContactWrapper> mapContactIdToContactWrapper {get;set;}  // map to contain contact id to contactwrapper
public Map<String, boolean> mapFieldNameToIsEditable        {get;set;}  // map to contain field api name to editable accessibility
public Id idSelectedContactId                               {get;set;}  // this will contain the selected contact id for delete
public Account currentAccount                               {get;set;}  // this is the standard controller account 
public String newContactUrl                                 {get;set;}
public String mergeContactUrl                               {get;set;}
public Boolean isCorporateAccount                           {get;set;}
public Boolean showInactiveContacts                         {get;set;}
/* End - Variables */

 /* Start - Constructor */
public SL_EnhancedContactRelatedListCtrl(ApexPages.StandardController stdController)
{
    mapFieldNameToIsEditable = new Map<String, boolean>();
    showInactiveContacts = false;
    currentAccount = (Account)stdController.getRecord(); // assign the account to variable   
    isCorporateAccount = [SELECT DeveloperName FROM RecordType WHERE Id= :currentAccount.RecordTypeId].DeveloperName=='Corporate_Account';
    fetchContacts(); 
    PageReference dummyPR = new PageReference('/003/e?retURL=%2F'+currentAccount.Id+'&accid='+currentAccount.Id);
    newContactUrl = dummyPR.getUrl();
    dummyPR = new PageReference('/merge/conmergewizard.jsp?retURL=%2F'+currentAccount.Id+'&id='+currentAccount.Id);
    mergeContactUrl = dummyPR.getUrl();
}
/* End - Constructor */

/**
* @MethodName : fetchContacts
* @Param      : 
* @Description: This method will fetch the all contact related to accounts 
**/
public void fetchContacts()
{
    mapContactIdToContactWrapper = new Map<Id, ContactWrapper>();
    List<String> lstContactFields = new List<String>();

<<snip>>

    Id idParentAccountId = currentAccount.Id;
    strQueryContact += String.join( lstContactFields, ', ');
    strQueryContact = lstContactFields.size()>0 ? strQueryContact+', ' : strQueryContact;
    strQueryContact += 'Id, Name,(SELECT Id, Account__r.Practice__r.Name, Contact__c FROM Contact_Relationships__r WHERE Account__r.Practice__r.Name != null)'+
                        ' FROM Contact WHERE '+((!isCorporateAccount) ? 'AccountId' : 'Account.Corporate_Account__c')+'=:idParentAccountId';
    if(!showInactiveContacts){
        strQueryContact += ' AND Contact.Active__c = TRUE';
    }

EDIT 2

This is what I currently have:

<apex:page standardController="Account" extensions="SEnhancedContactRelatedListCtrl" sidebar="false" showHeader="false">
<apex:form id="frm">
    <base target="_top"/>
    <apex:stylesheet value="{!URLFOR($Resource.SL_EnhancedContactRelatedList, 'css/jquery.dataTables.min.css')}"/>
    <apex:includeScript value="{!URLFOR($Resource.SL_EnhancedContactRelatedList, 'js/jquery-1.11.3.min.js')}"/>
    <apex:includeScript value="{!URLFOR($Resource.SL_EnhancedContactRelatedList, 'js/jquery.dataTables.min.js')}"/>

    <style>
       <<snip>>
    </style>
    <apex:actionFunction action="{!delContactRecord}" name="delContactAF" rerender="frm" status="counterStatus">
        <apex:param name="contactId" value="" assignTo="{!idSelectedContactId}"/>
    </apex:actionFunction>

    <apex:outputpanel rendered="{!!isCorporateAccount}" >
        <a href="{!newContactUrl}" target="_top" style="margin:4px">New Contact</a>
        <a href="{!mergeContactUrl}" target="_top" style="margin:4px">Merge Contact</a>
        <a href="/003?id={!currentAccount.Id}&rlid=RelatedContactList" target="_top" style="margin:4px">View All Contacts</a>
    </apex:outputpanel>
    <apex:commandLink action="{!toggleInactive}" value="Toggle" >
        <apex:actionSupport
            event="OnClick"
            reRender="frm"
            status="conterStatus" />
    </apex:commandLink>

At the Account Page layout the link can be click in the vf component:

enter image description here

When clicked it just brings up the vf page without the Account page layout:

enter image description here

EDIT 3

The toggle works in IE it refreshes the vf component and not the whole page. In Chrome and Firefox no success though.

  • 1
    I don't believe that <apex:outputLink> supports the rerender argument. If your desire is to re-render a portion of the page then you'll need to incorporate the rerender into there somewhere. I haven't used outputLink a lot but you could try putting an <apex:actionSupport> inside the <apex:outputLink> and </apex:outputLink> tags. Something like... <apex:outputLink> <apex:actionSupport event="onclick" rerender="form" action="{!toggleInactive}" /> </apex:outputLink> - you also need a pageBlockSection with the id of "form" so that the page knows what to rerender – Morgan Marchese Sep 28 '16 at 19:02
  • That doesn't seem to work for me. I get a really long link returned that comes back with url does not exist: npdtestdev--dev.cs13.my.salesforce.com/servlet/… – Dan Wooding Sep 28 '16 at 19:48
  • Can you elaborate a bit on your requirement? What value are you trying to set/pass into the controller? Can you post the content of your controller? What does the {!toggleInactive} method in the controller extension actually do? – Morgan Marchese Sep 28 '16 at 20:23
  • @MorganMarchese does that help? – Dan Wooding Sep 28 '16 at 20:32
  • Okay so first thing I notice is that {!toggleInactive} isn't even a method in your controller - so that's why the action of {!toggleInactive} isnt doing anything. Give me a few minutes and I'll pull up some code from one of my VF pages and see if I can create a usable example for you – Morgan Marchese Sep 28 '16 at 23:06
1

Your controller contains a boolean, showInactiveContacts, but doesn't appear to have any method that actually toggles it from true/false or false/true (unless you cut out that part of the controller) - Also I see that your constructor is setting it to false automatically - you'll want to get rid of that to avoid your constructor just setting it to false on every page load.

You'll first need to create the {!toggleInactive} method that will flip that switch for you. Bare bones it might look something like this:

public void toggleInactive(){
    if(!showInactiveContacts){
        showInactiveContacts = true
    }
    else{
        showInactiveContacts = false
    }
}

(If showInactiveContacts is false, toggle to true, else toggle to false)

Then you need a link that can call that toggle method on click. Like I said, I don't use apex:outputLink often but I think it would look like this:

<apex:outputLink value="Toggle Inactive Contacts">
    <apex:actionSupport event="onclick" action="{!toggleInactive}" rerender="form" />
</apex:outputLink>

Lastly, you need to re-render. I don't know if you want to reload the whole page or just re-render a certain section, but if you want to just re-render without a full page load then you should wrap your main contact display <table> area in a managed element. For example: putting an <apex:PageBlock id="form"> </apex:PageBlock> block around your table, or your div that surrounds your table. By using a managed element and assigning it the id of 'form', and having the rerender="form" on the actionSupport, the VF page should re-render the section without the need to reload the whole page.

If however you are trying to reload the whole page you can probably just use standard javascript using the onComplete attribute on the actionSupport:

<apex:outputLink value="Toggle Inactive Contacts">
    <apex:actionSupport event="onclick" action="{!toggleInactive}" rerender="form" onComplete="window.top.location.reload();" />
</apex:outputLink>

Please be advised I haven't tested any of this code, it's just a loose example of what you'll probably want to work on implementing that I wrote based on some code I have in one of my controllers that serves a similar purpose. Probably can't just copy/paste it into your controller and hit the ground running but should help I hope.

  • This is good I took info from here and I found a blog post that was helpful as well. blog.jeffdouglas.com/2010/03/03/… I got the link to set the value to true and the correct records show up. The link opens a new tab though and displays the vf page. It's not refreshing the page. – Dan Wooding Sep 29 '16 at 13:54
  • Can you post the code block of the link in question as it exists right now? – Morgan Marchese Sep 29 '16 at 14:34
  • Not sure why functionality in IE would differ from FF/Chrome, and I don't see a target="_blank" that would explain the new tab scenario you're facing. Not sure if it will make a difference but since you're using <apex:commandLink> now, you could move your rerender and your status directly to the link and get rid of the <apex:actionSupport> altogether. Try like this: <apex:commandLink action="{!toggleInactive}" value="Toggle" rerender="frm" status="conterStatus" /> - if that doesn't change anything, you could also try adding target="_self" to the commandLink params maybe? – Morgan Marchese Sep 29 '16 at 16:27
  • It's very strange I logged a ticket with Salesforce Support because it worked in the one browser and not the other. The commandLink didn't like the reRender in it. The target="_self" didn't work in the actionSupport. I think I'm stuck till support looks into the problem unless anyone else here has seen the issue before. In my searches no one created a question about it... – Dan Wooding Sep 29 '16 at 16:35
  • Might be worth creating a separate question about it @DanWooding so that it gets appropriate traffic. People might pass over this one since its not specific to that issue. – Morgan Marchese Sep 29 '16 at 18:03

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.