Pages

Monday, September 29, 2008

How to Dynamically Change actionStatus Content? - Part II

In part I of this article we explored what components we will need to be able to dynamically view actionStatus based on different actions that takes place the Visualforce page.

Now lets piece the page components together and see how we can have a javascript function which changes the actionStatus start facet's content on the fly and calls a controller's method as well.



<apex:page controller="myPageController" tabStyle="Account">
<apex:form >
<apex:sectionHeader title="My Page" />
<apex:pageBlock title="" id="pageBlock">
<apex:pageBlockButtons location="top">
<apex:inputField id="accountType" value="{!Account.Type}" />
<apex:commandButton value="View" action="{!ViewAccounts}" id="theButton" rerender="pageBlock"></apex:commandButton>
</apex:pageBlockButtons>
<apex:pageMessages ></apex:pageMessages>
<!-- defines a javascript function which calls a Controller's method -->
<apex:actionFunction action="{!ShowSelected}" name="RowMethodCall" rerender="pageBlock" status="status">
<apex:param name="selectedAccount" assignTo="{!selectedAccount}" value=""/>
</apex:actionFunction>
<!-- define a start facet within the actionStatus that has a div with defined id visible to the whole HTML document -->
<apex:actionStatus id="status">
<apex:facet name="start">
<div id="statusTemplate">Working...</div>
</apex:facet>
</apex:actionStatus>

<apex:pageBlockTable value="{!accounts}" var="a" rendered="{!NOT(ISNULL(accounts))}">
<apex:column >
<apex:facet name="header">Account Name</apex:facet>
<apex:outputLink value="/{!a.Id}" target="_blank">{!a.Name}</apex:outputLink>
</apex:column>
<apex:column value="{!a.type}"></apex:column>
<apex:column >
<apex:facet name="header">Action</apex:facet>
<a href="javascript:DoTask('{!a.Id}');">Execute</a>
<div style="display:none" id="{!a.Id}">
Processing {!a.Name} ...
</div>
</apex:column>
</apex:pageBlockTable>
</apex:pageBlock>
<script type="text/javascript">
function DoTask(accountId)
{

var accountStatus = document.getElementById(accountId);
if (accountStatus && accountStatus.innerHTML)
{
document.getElementById('statusTemplate').innerHTML = accountStatus.innerHTML;
}

RowMethodCall(accountId);
}
</script>
</apex:form>
</apex:page>

As you can see in the code use of actionFunction component allows us to define a javascript function which can be called from the client-side (user's browser) to safely call a controller's method. I called the function name for this exmaple: "RowMethodCall" which will use the page message to show the selected Account Name to the user.

This function needs the selected Account ID as a parameter to be able to show the seleced account.

The Action column in the pageBlockTable component calls another javascript function called: "DoTask". DoTask also receive the account Id as a parameter and here is the trick:

Since account Ids are unique, I named the Id of the Div element equal to the Account id (which will contain a template that we are suppose to show as cutom actionStatus for each Account).

This way DoTask javascript function will be able to read the innerHTML content of the div in the action column and apply to the content of the actionStatus start facet div element.

Well, and now if you wondered how the custom controller is like, here you go:


public class myPageController {

private Account acc = new Account();

private List<Account> accs;

private string selectedAccount;

public Account getAccount()

{

return acc;

}

public void setAccount(Account a)

{

acc = a;

}

public List<Account> getAccounts()

{

return accs;

}

public string getSelectedAccount()

{

return selectedAccount;

}

public void setSelectedAccount(string value)

{

selectedAccount = value;

}

public PageReference ViewAccounts()

{

if (acc.Type == null)

{

//view a message because validation has failed.

ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO,'Validation Failed: Select an item fron the dropdown list.'));

return null;

}

string AccountType = acc.Type;

accs = [Select id, name, type from Account where type= :AccountType limit 20];

if (accs == null || accs.size() == 0)

{

ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO,'No data found to be shown.'));

}

return null;

}

public PageReference ShowSelected()

{

if (selectedAccount != null && selectedAccount != '')

{

for(Account a: accs)

{

if (a.Id == selectedAccount)

{

string Msg = a.Name + ' Account is selected.';

ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO,Msg ));

}

}

}

return null;

}

}


No comments:

Post a Comment