I've reduced my issue to the following example:
<apex:page >
<apex:variable var="blank" value="" />
<p> Contains(blank, 'foo'): <apex:outputText value="'TRUE'" rendered="{!CONTAINS(blank, 'foo')}" /></p>
<p> Not(Contains(blank, 'foo')): <apex:outputText value="'TRUE'" rendered="{!NOT(CONTAINS(blank, 'foo'))}" /></p>
<p> NULLVALUE(blank, 'x'): <apex:outputText value="{! NULLVALUE(blank,'XXXXX')}" /></p>
<p> BLANKVALUE(blank, 'x'): <apex:outputText value="{! BLANKVALUE(blank,'XXXXX')}" /></p>
<p> ISBLANK(blank, 'x'): <apex:outputText value="{! ISBLANK(blank)}" /></p>
</apex:page>
Which produces:
Contains(blank, 'foo'):'TRUE'
Not(Contains(blank, 'foo')):'TRUE'
NULLVALUE(blank, 'x'):
BLANKVALUE(blank, 'x'):
ISBLANK(blank, 'x'):false
How can Contains(blank, 'foo')
and Not(Contains(blank, 'foo'))
both return true? Why doesn't BLANKVALUE or ISBLANK recognize the var blank as being blank?
I took this a step further, and created this controller:
public class formulaTestController {
public string getNullValField() { return null;}
public string getBlankValField() {return ''; }
}
If I add this controller to the page and change the variable to <apex:variable var="blank" value="{!blankValField}" />
, I get the same results as above. If I change it to <apex:variable var="blank" value="{!nullValField}" />
, I get this:
Contains(blank, 'foo'):'TRUE'
Not(Contains(blank, 'foo')):'TRUE'
NULLVALUE(blank, 'x'):XXXXX
BLANKVALUE(blank, 'x'):XXXXX
ISBLANK(blank, 'x'):true
So it appears that BLANKVALUE and ISBLANK really operate on nulls, but not on blanks. Is this expected? Especially w/r/t BLANKVALUE, as NULLVALUE also exists. And why do the Contains()
and (Not(Contains())
tests still produce the same result?!
In the end, I need to reliably handle a controller value that may be blank or null, treating these as special cases in my VF logic. How can I do so?
EDIT: Per suggested answer, I tried wrapping Contains test in IF(). Note that I moved the formula into outputText's Value to make the result explicit:
<apex:page >
<apex:variable var="blank" value="" />
<p> IF(CONTAINS(blank, 'foo'),true, false): <apex:outputText value="{!IF(CONTAINS(blank, 'foo'),true, false)}" /></p>
<p> IF(NOT(CONTAINS(blank, 'foo')),true, false): <apex:outputText value="{!IF(NOT(CONTAINS(blank, 'foo')),true, false)}" /></p>
<p> IF(CONTAINS(blank, 'foo'),'true', 'false'): <apex:outputText value="{!IF(CONTAINS(blank, 'foo'),'true', 'false')}" /></p>
<p> IF(NOT(CONTAINS(blank, 'foo')),'true', 'false'): <apex:outputText value="{!IF(NOT(CONTAINS(blank, 'foo')),'true', 'false')}" /></p>
</apex:page>
No change:
IF(CONTAINS(blank, 'foo'),true, false):false
IF(NOT(CONTAINS(blank, 'foo')),true, false):false
IF(CONTAINS(blank, 'foo'),'true', 'false'):false
IF(NOT(CONTAINS(blank, 'foo')),'true', 'false'):false
UPDATE: As noted by @tlfu below, Salesforce is now tracking this issue. You may recognize the issue description :)