is it possible to check for a specific key in a map i.e., whether it exists or not in VISUALFORCE page?
Based on this i need to render a pageblocktable.
is it possible to check for a specific key in a map i.e., whether it exists or not in VISUALFORCE page?
Based on this i need to render a pageblocktable.
No, there's no way to tell if a key exists or not. We don't have access to "containsKey", and any attempt to reference a key that doesn't exist will cause your code to crash and burn catastrophically.
Visualforce Error
Help for this Page
Map key 'value' not found in map
Error is in expression '{!not(isnull(keys[key]))}' in component <something> in page xyz
This is related to bug W-1065879 (according to an old forum post).
The solution is to check the key in Apex Code, and prevent the rendering of the element or component before the attempted access.
Here's an example used in live code:
public with sharing class orderCreateController {
public Map<Id,Boolean> selectId { get; set; }
public Map<Id,Quote> quoteList { get; set; }
// Irrelevant code redacted here
// FIX FOR BUG W-1065879
public wrapper[] getwrapperlist() {
wrapper[] items = new wrapper[0];
if(quotelist != null) {
for(id quoteid:quotelist.keyset()) {
items.add(new wrapper(this,quoteid));
}
}
return items;
}
public class wrapper {
public wrapper(orderCreateController c,id recordid) {
con = c;
id = recordid;
}
public boolean selected { get { return con.selectid.get(id); } set { con.selectid.put(id,value); } }
public quote quote { get { return con.quotelist.get(id); } }
private id id;
private orderCreateController con;
}
}
By iterating over {!wrapperlist}, we can create a pseudo-wrapper that will prevent non-existent keys from appearing.
I just realized that this code takes some explaining. You can select from a list of quotes. The map may not always be populated with boolean values, so this wrapper class protects the Visualforce map controller from croaking.
You should really keep this type of logic out of a Visualforce page. A Visualforce page should be used simply for View logic. Instead, add it as part of your controller:
Apex
public Boolean getRenderPageBlockTable(){
return mapToCheck.containsKey('keyToCheck');
}
Visualforce
<apex:pageBlockSection rendered="{!renderPageBlockTable}">
...
</apex:pageBlockSection>
You can generate a delimited string with all the keys of the map in controller like this:
this.delimitedString = String.join(new List<String>(yourMap.keySet()), ',');
and then use the CONTAINS()
formula function to check for the existence of that key in your Visualforce page.
<apex:outputText rendered="{!CONTAINS(delimitedString, key)}">
{!yourMap[key]}
</apex:outputText>
Actually, you can build that natively on Visualforce Page, without any further variables. You need to use an apex:repeat, iterate over it, and inside the apex:repeat you may use an outputText (or similar and render the outputText just in case the iterated value matches your expected value. For example:
<apex:repeat value="{!yourMapVariable}" var="key"> <!--yourMapVariable is a map and you are not sure whether it contains or not the key 'Name' -->
<apex:outputText rendered="{!key=='Name'}"> <!-- kind of containsKey(...) -->
{!yourMapVariable[key]} <!-- this is now safe and will never produces an exception -->
</apex:outputText>
</apex:repeat>
Instead of checking in VF page, I check in the code itself when you are populating the List/Map. I'm also using an of list items to display
personReferList
is full list of apex:repeat.
//creating a new List to hold the records which exists in map
List<Person__c> PIList = new List<Person__c>();
//looping the list of records displayed in VF page
for(Person__c pi: personReferList){
//checking if all the records are in the Map
if(mapPersonRef.containsKey(pi.Id)){
//If yes, adding it to a new list.
PIList.add(pi);
}
}
//clearing the original list first
personReferList.clear();
*//adding the from original list to the original list*
personReferList.addAll(PIList);