function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
DavserDavser 

Inline VisualForce "IF" statement

Hi all,
I am trying to display some content, which is dependent in a Boolean variable in my controller. First I tried the following code:
 
Code:
{!IF({!isBrandedChannel},"SOMECONTENT", "SOMEOTHERCONTENT")} 

 where {!isBrandedChannel} is the Boolean variable. This wouldn't compile in Eclipse and hence wouldn't save to the server.
 
Next I tried using the "rendered" tag of the Visualforce component. However the limitation here is that I need 2 components that would be declared something like:
 
Code:
<apex:repeat value="{!newIOs}" rendered="{!isBrandedChannel}" var="io">

and

<apex:repeat value="{!newIOs}" rendered="NOT({!isBrandedChannel})" var="io">

 
However the "NOT" function doesn't work here.
 
Eventually I declared 2 variables in my controller, one the normal isBrandedChannel variable, the second giving me the inverse of this, and used these on my 2 seperate repeat components.
 
This seems strange to have to do this. Is there a better way?
 
 
mtbclimbermtbclimber
Yes, have one reference to {!newIOs} and in your controller return the right results based on the outcome of {!isBrandedChannel}
Then you don't need to worry about showing or hiding a particular component.

If what you output is different based on what is returned from {!newIOs} which
I can't tell is the case based on the limited code I can see here then yes, you'll need to
have different component definitions in your page with rendered attribute values bound
accordingly.

I do see syntactic problems with your expressions however:

Code:
{!IF({!isBrandedChannel},"SOMECONTENT", "SOMEOTHERCONTENT")} 

 That is illegal, it should look like this:

Code:
{!IF(isBrandedChannel,"SOMECONTENT", "SOMEOTHERCONTENT")} 

 
Also this:

Code:
<apex:repeat value="{!newIOs}" rendered="NOT({!isBrandedChannel})" var="io">

 Should look like this:

Code:
<apex:repeat value="{!newIOs}" rendered="{!NOT(isBrandedChannel)}" var="io">

dchasmandchasman
The problem in your examples is that you are not delimiting your expressions correctly - everything inside the {!} is an expression, anything outside that area is just markup that visualforce is going to essentially ignore:

Code:
{!IF({!isBrandedChannel},"SOMECONTENT", "SOMEOTHERCONTENT")} 

should read

{!IF(isBrandedChannel, 'SOMECONTENT', 'SOMEOTHERCONTENT')}

 same thing again here:

Code:

<apex:repeat value="{!newIOs}" rendered="NOT({!isBrandedChannel})" var="io">
should read

<apex:repeat value="{!newIOs}" rendered="{!NOT(isBrandedChannel)}" var="io">

or

<apex:repeat value="{!newIOs}" rendered="{! !isBrandedChannel}" var="io">

if you prefer the bang operator syntax (I tend to use not() just because the double !'s can trip folks up...

BTW take a look at this  to see some discussion on where we are on adding <apex:if> and <apex:case> kind of tags 
to make alternate selection simpler (hint you might want to vote for this idea
http://ideas.salesforce.com/article/show/10089418/Add_conditional_block_Visualforce_components_eg_ltapexif_ltapexcase_etc?skin=null

Please promote/vote on this idea if you want to see us add this functionality :-)

DavserDavser

Thanks for the replies so far, the nested {! tags was the problem. However, I note that in the Visualforce developer guide (summer 2008), the following is given as example code for the NOT function

Code:
{!IF(NOT(Account.IsActive)){!SaveAcct}, {!ReportAcct}} 

which would appear to contain nested tags, but perhaps the nested tags only applies to the conditions of the if statement?

So my problem has moved on a little. I am trying to conditionally output a column in a table, depending on the value of isBrandedChannel. For the body of the table I am using 2 conditional repeat components which works fine. The problem I have is with the header of the table. I need to conditionally output the following code, to include the column header:

Code:
<td>Branded&nbsp;Channel</td>

When I use the IF statement to output HTML, it produces "escaped" HTML. I couldn't see a way around this. So I decided to use the outputText component like so:

Code:
<apex:outputText rendered="{!isBrandedChannel}" escape="false" value="<td>Branded&nbsp;Channel</td>" />


However I got an error in Eclipse saying "The value of attribute "value" associated with an element type "apex:outputText" must not contain the '<' character. at line 22". This seemed very strange given that there is an "escape" attribute on this component.

I also tried this with the following format:

Code:
<apex:outputText rendered="{!isBrandedChannel}" escape="false"><td>Branded&nbsp;Channel</td></apex:outputText>


 which is actually the closest I've gotten to getting it to work the way I want to, however for some reason this inserted a whole pile of extra table tags and pushed this column header out to the side.

Anyone got any suggestions on a way around this?


 

 

mtbclimbermtbclimber
I think there is a better way here. Can you post your page and controller in their entirety please?
DavserDavser
OK, so I've renamed a lot of the variables etc., but here is the controller:
 
Code:
public class IOWizardController {

 Opportunity opportunity;
 Integer amtG;
 Integer amtD;
 List<IOWrapper> newIOs = new List<IOWrapper>();
 ID opportunityId;
 Boolean isBC = false;

 public IOWizardController(){
  opportunity = [select Id,Deal_Type__c from Opportunity where Id=:ApexPages.currentPage().getParameters().get('id')];
  if(opportunity.Deal_Type__c == 'BCP')
   isBC = true;
 }

 public Integer getAmtG(){
  return amtG;
 }

 public void setAmtG(Integer amtG){
  this.amtG = amtG;
 }

 public Integer getAmtD(){
  return amtD;
 }

 public void setAmtD(Integer amtD){
  this.amtD = amtD;
 }

 public void setIsBC(Boolean isBC){
  this.isBC = isBC;
 }

 public Boolean getIsBC(){
  return isBC;
 }

 public List<IOWrapper> getNewIOs(){
  return newIOs;
 }

 public PageReference step1(){
  newIOs = new List<IOWrapper>();
  return Page.IOWizardP1;
 }

 public PageReference step2(){
  Integer totalIO = amtG * amtD;

  for(Integer i = 0; i < totalIO; i++){
   IO__c io = new IO__c();
   io.Opportunity__c = opportunity.Id;
   IOWrapper iOrder = new IOWrapper(io,i);
   newIOs.add(iOrder);
  }

  return Page.IOWizardP2;
 }

 public PageReference save(){
  List<IO__c> ioForUpdate = new List<IO__c>();
  for(IOWrapper iOWrapper : newIOs){
   ioForUpdate.add(iOWrapper.iod);
  }
  insert ioForUpdate;

  PageReference opptyPage = new PageReference('/' + opportunity.Id);
       opptyPage.setRedirect(true);

       return opptyPage;
 }

 public PageReference cancel(){
  PageReference opptyPage = new PageReference('/' + opportunity.Id);
       opptyPage.setRedirect(true);

       return opptyPage;
 }

 public class IOWrapper{
  IO__c iod;
  Integer rowNumber;

  public IOWrapper(IO__c iod, Integer rowNumber){
   this.iod = iodr;
   this.rowNumber = rowNumber;
  }

  public IO__c getIOr(){
   return iod;
  }
  public void setIO(IO__c iod){
   this.iod = iod;
  }

  public Integer getRowNumber(){
   return rowNumber;
  }
  public void setRowNumber(Integer rowNumber){
   this.rowNumber = rowNumber;
  }
 }
}

 
And here is the page (this is step 2 of a 2 step process
 
Code:
<apex:page controller="IOWizardController" tabStyle="Opportunity">
<style>
 .headerTableCell{
  padding-left: 5px;
  padding-bottom: 10px;
  font-weight: bold;
 }
 .innerTableCellInput{
  padding-right: 10px;
  padding-bottom: 10px;
 }
</style>
<apex:sectionHeader title="Create Deal IOs" subtitle="Step 2 of 2">
 <apex:form >
  <apex:pageBlock title="IO Detail Information">
   <apex:pageBlockButtons >
    <apex:commandButton value="Prev" action="{!step1}"/>
    <apex:commandButton value="Save" action="{!save}"/>
    <apex:commandButton value="Cancel" action="{!cancel}"/>
   </apex:pageBlockButtons>
   <apex:pageBlockSection >
    <table style="width:100%">
    <tr>
     <td class="headerTableCell">DD</td>
     <td class="headerTableCell">G</td>
     <td class="headerTableCell">TCD</td>
     <td class="headerTableCell">LP</td>
     <apex:outputText rendered="{!isBC}" escape="false"><td class="headerTableCell">BC</td></apex:outputText>
    </tr>
    <apex:repeat value="{!newIOs}" rendered="{!NOT(isBC)}" var="io">
     <tr>
      <td class="innerTableCellInput"><apex:inputField value="{!io.iod.Edd__c}"/></td>
      <td class="innerTableCellInput"><apex:inputField value="{!io.iod.G__c}"/></td>
      <td class="innerTableCellInput"><apex:inputField value="{!io.iod.Totald__c}"/></td>
      <td class="innerTableCellInput"><apex:inputField value="{!io.iod.D__c}"/></td>
     </tr>
    </apex:repeat>
    <apex:repeat value="{!newIOs}" rendered="{!isBC}" var="io">
     <tr>
      <td class="innerTableCellInput"><apex:inputField value="{!io.iod.Edd__c}"/></td>
      <td class="innerTableCellInput"><apex:inputField value="{!io.iod.G__c}"/></td>
      <td class="innerTableCellInput"><apex:inputField value="{!io.iod.Totald__c}"/></td>
      <td class="innerTableCellInput"><apex:inputField value="{!io.iod.D__c}"/></td>
      <td class="innerTableCellInput"><apex:inputField value="{!io.iod.BC__c}"/></td>
     </tr>
    </apex:repeat>
    </table>
   </apex:pageBlockSection>
  </apex:pageBlock>
 </apex:form>
</apex:sectionHeader>
</apex:page>

 
Any further help here would be greatly appreciated!
mtbclimbermtbclimber
Thanks for posting your page/controller code.

I think I have a handle on what you are trying to do.  Your best bet is to try to use our components before dropping to HTML. In this case I suspect you were not aware of pageblocktable and how you can leverage the column's rendered attribute directly.

I took a stab at how I thought you might want it to be but I did make a few mods:

1) Changed your controller accessors to use the new property syntax (didn't touch your inner, wrapper class)
2) Removed some custom fields since I didn't feel like creating them :)
3) Switched to use the standard type field on oppty (again, my laziness)
4) removed the opportunityId member from the controller - didn't seem to be used
5) added a debugging pageblock, just click the checkbox to toggle the visibility of the second column
6) Removed page references from your wizard navigation (more dependency laziness :) )
7) Cut out action method code since it's not needed to convey the goal

Let me know if I am on the right track here.....

Controller:
public class IOWizardController {
public Opportunity opportunity { get; set; }
public Integer amtG { get; set; }
public Integer amtD { get; set; }
public List<IOWrapper> newIOs {
get{
if(newIOs == null) newIOs = new List<IOWrapper>();
return newIOs;
}
set;
}

public Boolean isBC{
get {
if(isBC == null) isBC = false;
return isBC;
}
set;
}

public IOWizardController(){
//opportunity = [select Id,Deal_Type__c from Opportunity where Id=:ApexPages.currentPage().getParameters().get('id')];
opportunity = [select Id,Type from Opportunity limit 1];
//if(opportunity.Deal_Type__c == 'BCP')
if(opportunity.Type == 'New Customer') isBC = true;
}

public PageReference step1(){
//cut for sample
return null;
}

public PageReference step2(){
//cut for sample

return null;
}

public PageReference save(){
//cut for sample

return null;
}

public PageReference cancel(){
//cut for sample

return null;
}

public class IOWrapper{
IO__c iod;
Integer rowNumber;

public IOWrapper(IO__c iodr, Integer rowNumber){
this.iod = iodr;
this.rowNumber = rowNumber;
}

public IO__c getIOr(){
return iod;
}
public void setIO(IO__c iod){
this.iod = iod;
}

public Integer getRowNumber(){
return rowNumber;
}
public void setRowNumber(Integer rowNumber){
this.rowNumber = rowNumber;
}
}
}

 
Page:
<apex:page controller="IOWizardController">
<apex:sectionHeader title="Create Deal IOs" subtitle="Step 2 of 2"/>
<apex:form >
<apex:pageBlock title="Debug">
<apex:pageBlockSection >
<apex:outputField value="{!opportunity.id}"/>
<apex:outputField value="{!opportunity.type}"/>
<apex:pageblockSectionItem>
<apex:outputLabel for="isBC" value="Toggle isBC"/>
<apex:inputCheckbox value="{!isBC}" id="isBC">
<apex:actionSupport event="onchange" rerender="IOBlock" status="status"/>
</apex:inputCheckbox>
</apex:pageblockSectionItem>
<apex:pageBlockSectionItem>
<apex:actionStatus startText="requesting...." id="status"/>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
</apex:pageblock>
<apex:pageBlock title="IO Detail Information" id="IOBlock">
<apex:pageBlockButtons >
<apex:commandButton value="Prev" action="{!step1}"/>
<apex:commandButton value="Save" action="{!save}"/>
<apex:commandButton value="Cancel" action="{!cancel}"/>
</apex:pageBlockButtons>
<apex:pageBlockSection columns="1">
<apex:pageBlockTable value="{!newIOs}" var="io">
<apex:column headerValue="Edd">
<apex:inputField value="{!io.iod.Edd__c}"/>
</apex:column>
<apex:column headerValue="G" rendered="{!NOT(isBC)}">
<apex:inputField value="{!io.iod.G__c}"/>
</apex:column>
</apex:pageBlockTable>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>

 





Message Edited by mtbclimber on 06-06-2008 01:15 PM
DavserDavser
Thanks Andrew, that is exactly what I was trying to do. I just didn't realise that you could have an input field inside the column tag like that. Great stuff, and thanks for the quick replies, was extremely helpful.