[SalesForce] How To Show Help Text Within a apex:pageblocksectionitem From Within a Dynamic Component

So recently, I came upon an issue using my dynamic component within a pageBlock. As some may know, you cannot properly display help text (icon with a help text when you hover), within a pageBlockSectionItem. In my use case, I was generating input fields through the use of fieldsets (very useful by the way). However, help text was needed for a small amount of fields.

So the following VisualForce:

<apex:pageBlockSection columns="1" title="Important Information" id="Information" collapsible="true">

               <apex:dynamicComponent componentValue="{!Information}"/>

               <apex:pageBlockSectionItem >
                      .... Other stuff that must be arranged differently...
               </apex:pageBlockSectionItem >
</apex:pageBlockSection>

This would display my input fields within the dynamic component but, my help text wouldn't show.

The code to generate the dynamic component looks something like this:

public Component.Apex.PageBlockSection Information() 
{
   Component.Apex.PageBlockSection InformationSection = new Component.Apex.PageBlockSection();

   for(Schema.FieldSetMember Field : this.InformationSection)
   {
      Component.Apex.InputField Input = new Component.Apex.InputField(Label = Field.getLabel());
      Input.expressions.value = '{!'+Field.getFieldPath() +'}';
      InformationSection.childComponents.add(Input);    
   }
   return OpportunityInformationSection;
}

So, how exactly would I setup the method to show the input field with the appropriate help text?

Best Answer

Thnakfully, one of my associates came into a very similar issue. However, he hardcoded it into his VisualForce page. I did not want to remove my dynamic component since there were other things I needed to account for (some fields needing to be output, some fields needed onchange methods, some needed unique Ids, etc.). So, after looking at his solution, I came up with a way to make it work.

The new dynamic component code looks like this (I know it looks a tad ugly :-P):

public Component.Apex.PageBlockSection Information() 
{
   Component.Apex.PageBlockSection InformationSection = 
      new Component.Apex.PageBlockSection();
   Set<String> FieldsThatNeedHelpIcons = new Set<String>{'FieldA'};

   for(Schema.FieldSetMember Field : this.InformationSection)
   {
      if(FieldsThatNeedHelpIcons.contains(Field.getFieldPath()))
      {
         Component.Apex.PageBlockSectionItem InputWithHelp = new Component.Apex.PageBlockSectionItem();

         Component.Apex.OutputText Output = 
            new Component.Apex.OutputText(Escape = false);

         //Please make sure the label id is unique and matches up with help Id
         Output.expressions.value = '<label id="' + Field.getFieldPath().substring(0, 3) +  
         '" for = "'+Field.getFieldPath() +'">' + Field.getLabel() + 
         '<span class="helpButton" id="'+ Field.getFieldPath().substring(0, 3) +
         '-_help"><img src="/s.gif" alt="" class="helpOrb" title="" /><script>sfdcPage.setHelp(\'' + 
         Field.getFieldPath().substring(0, 3) +
         '\', \'{!HTMLENCODE($ObjectType.Opportunity.Fields.' + 
         Field.getFieldPath() +'.inlineHelpText)}\');</script></span></label>';

         Component.Apex.InputField Input = 
            new Component.Apex.InputField(Label = Field.getLabel(), Id = Field.getFieldPath());
         Input.expressions.value = '{!'+Field.getFieldPath() +'}';

         InputWithHelp.childComponents.add(Output);
         InputWithHelp.childComponents.add(Input);
         InformationSection.childComponents.add(InputWithHelp);
      }
      else
      {
         Component.Apex.InputField Input = new Component.Apex.InputField(Label = Field.getLabel());
         Input.expressions.value = '{!'+Field.getFieldPath() +'}';
         InformationSection.childComponents.add(Input);
      }    
   }
   return OpportunityInformationSection;
}

Basically, I injected some support code to inject the label, span tag, help image, and script using a dynamically generated apex:outputtext escaped to false. Since it is set to false, it will execute whatever I wish (caution is advised of course), specifically helping show the correct help text.