1

Background: I created a VisualForce page with the intention of embedding it inline into an Opportunity layout. I've used the standard Opportunity controller with a controller extension. On this page, there is a custom selectOption list with 5 values:

--None--, Tier 1, Tier 2, Tier 3, Custom

If you choose Tier 1, 2, or 3, a method runs via onchange actionSupport, and it updates the opp based on pre-defined conditions of each Tier, which I pull from a Custom Setting. If you choose --None--, it updates the opp back to null for all appropriate fields. In each of these scenarios, I also re-render the pageBlockSection that holds these fields, so that changes can be seen immediately upon changing the selectOption.

All of this works as expected, except for the 'Custom' selectOption...


Problem: When choosing the 'Custom' option from the picklist, I set a Boolean called isCustom to true, and then the same re-render occurs. This time however, the re-rendered section sees that isCustom is true. In the case of this Boolean being true, I hide all of the outputFields (via the render (true/false) param), and display inputFields instead, with the intent of allowing the user to enter custom rate information. However, for some reason these inputFields are rendering without field Labels, and I'm not sure why, how to resolve it, or if this is a bug.


Question: Why are my dynamically rendered inputFields not displaying field Labels?


Update, 7/23/2016 5:42 PM EST :

I tried to use <apex:outputLabel /> as suggested by Santanu below, but to no avail.

When I tried <apex:outputLabel value="{!field}" />, the resulting label was displaying the API names for the fields.

When I tried <apex:outputLabel value="{!Opportunity[field]}" />, the resulting label was displaying the value of each field in the fieldSet (showing 1.65% instead of showing "Transaction Fee")

I then tried just manually creating an inputField directly below the PageBlockSection, as it was suggested that inputFields only show BOTH the label and value if they are directly below (not in a repeat). This also resulted in just the field value (with no label) even when using the standard Opportunity controller and standard Name field (shown below):

<apex:pageBlockSection columns="1" id="rateCalc" title="Rate Calculator" rendered="true" >
            <apex:form >
            <apex:inputField value="{!Opportunity.Name}" />
            </apex:form>

VisualForce Page:

<apex:page standardController="Opportunity" extensions="PDOppMSIRatePicker_CX">
    <apex:pageBlock mode="detail">
        <apex:form >
            <label><b>Select Your Pricing Tier: </b></label>
            <apex:selectList id="SelectList1"  size="1" value="{!selectedTier}" style="height:30px;font-weight:bold;">
                <apex:selectOptions value="{!SelectList1List}"/>
                <apex:actionsupport event="onchange" rerender="rateCalc,rateCalcResults" action="{!updateRates}" />
            </apex:selectList>
        </apex:form>

    <br />

        <div style="width:49%;display:inline-block;">
            <apex:pageBlockSection columns="1" id="rateCalc" title="Rate Calculator" rendered="true">
                <apex:repeat value="{!$ObjectType.Opportunity.FieldSets.PDRatePickerFields}" var="field">
                    <!-- If Records Tier is NOT set to Custom, Display outputFields with appropriate Tier data on (re)render -->
                    <apex:outputField rendered="{!!isCustom}" value="{!Opportunity[field]}" />
                </apex:repeat>
                <apex:repeat value="{!$ObjectType.Opportunity.FieldSets.PDRatePickerFields}" var="field">
                    <!-- If Records Tier IS set to Custom, (isCustom = true), Display apex:form and inputFields for adding custom rate data on (re)render -->
                    <!-- PROBLEM AREA :: WHY ARE BELOW INPUT FIELDS INSIDE THE REPEAT NOT DISPLAYING LABELS? :: PROBLEM AREA -->
                    <apex:form rendered="{!isCustom}">
                        <apex:inputField value="{!Opportunity[field]}" />
                    </apex:form>
                </apex:repeat>
            </apex:pageBlockSection>
        </div>

        <div style="width:49%;display:inline-block;">
            <apex:pageBlockSection columns="1" id="rateCalcResults" title="Rate Calculator Results" rendered="true">
                <apex:repeat value="{!$ObjectType.Opportunity.FieldSets.PDRatePickerResultsFields}" var="field">
                    <apex:outputField value="{!Opportunity[field]}" />
                </apex:repeat>
            </apex:pageBlockSection>
        </div>
    </apex:pageBlock>
</apex:page>

Controller Extension:

public with sharing class PDOppMSIRatePicker_CX {

    private final Opportunity opp;

    public PDOppMSIRatePicker_CX(ApexPages.StandardController stdController) {
        this.opp = (Opportunity)stdController.getRecord();
    }


//Begin Controller Extension Code

    // Boolean Returns True if Selected Tier = -1, otherwise Returns False
    // If True - Render inputFields on the VF Page
    // If False - Render outputFields on the VF Page
    public Boolean isCustom {
        get{
            if(isCustom == false || isCustom == null){
                Opportunity record = [SELECT Selected_Tier__c FROM Opportunity WHERE Id =: opp.id];
                if(record.Selected_Tier__c == '-1'){
                    isCustom = true;
                }
                else{
                    isCustom = false;
                }
            }
            return isCustom;
        }
        set;
    }

    // String gets the last selected Tier for this record by lazy-loading if null and pulling the value from the related record.
    // Possible Record Values: -1, 0, 1, 2, 3
    public string selectedTier{
        get{
            if(selectedTier == null){
                Opportunity record = [SELECT Selected_Tier__c FROM Opportunity WHERE Id =: opp.id];
                selectedTier = record.Selected_Tier__c;
            }
            return selectedTier;
        }
        set;
    }

    // Build List of SelectOptions for different Selectable Tiers
    // Tier 1, 2, or 3 should result in pulling data from a Custom Setting and updating the record before rerendering the rate calculator with the new data
    // Custom should result in hiding the outputFields and rendering inputFields on rerender, for entering custom rates
    public List<SelectOption> getSelectList1List(){
        List<SelectOption> options = new List<SelectOption>();
        options.add(new SelectOption('0','--None--'));
        options.add(new SelectOption('1','Tier 1'));
        options.add(new SelectOption('2','Tier 2'));
        options.add(new selectOption('3','Tier 3'));
        options.add(new selectOption('-1','Custom'));
        return options;
    }   

    // The logic that commits changes to the record depending on the selectedTier value    
    public void updateRates(){  
        List<SelectOption> options = new List<SelectOption>();
        System.debug('MM++++ Rates selectedTier: ' +selectedTier);

        if(selectedTier=='0'){
            opp.MSI_Trans_Fee__c = null;
            opp.MSI_Pricing_Rate__c = null;
            opp.MSI_Monthly_Fee__c = null;
            opp.Selected_Tier__c = '0';
            selectedTier = '0';

            update opp;
            opp.recalculateFormulas();           
        }
        else if(selectedTier=='1'){
            PDStandardRates__c rates = PDStandardRates__c.getInstance('New Customer Tier 1');
            opp.MSI_Trans_Fee__c = rates.Transaction_Fee__c;
            opp.MSI_Pricing_Rate__c = rates.Pricing_Rate__c;
            opp.MSI_Monthly_Fee__c = rates.Monthly_Fee__c;
            opp.Selected_Tier__c = '1';
            selectedTier = '1';
            System.debug('Opp Tier: ' + opp.Selected_Tier__c);
            isCustom = false;

            update opp;
            opp.recalculateFormulas();
        }
        else if(selectedTier=='2'){
            PDStandardRates__c rates = PDStandardRates__c.getInstance('New Customer Tier 2');
            opp.MSI_Trans_Fee__c = rates.Transaction_Fee__c;
            opp.MSI_Pricing_Rate__c = rates.Pricing_Rate__c;
            opp.MSI_Monthly_Fee__c = rates.Monthly_Fee__c;
            opp.Selected_Tier__c = '2';
            selectedTier = '2';
            System.debug('Opp Tier: ' + opp.Selected_Tier__c);
            isCustom = false;

            update opp;
            opp.recalculateFormulas();
        }
        else if(selectedTier=='3'){
            PDStandardRates__c rates = PDStandardRates__c.getInstance('New Customer Tier 3');
            opp.MSI_Trans_Fee__c = rates.Transaction_Fee__c;
            opp.MSI_Pricing_Rate__c = rates.Pricing_Rate__c;
            opp.MSI_Monthly_Fee__c = rates.Monthly_Fee__c;
            opp.Selected_Tier__c = '3';  
            selectedTier = '3';
            System.debug('Opp Tier: ' + opp.Selected_Tier__c);
            isCustom = false;

            update opp;
            opp.recalculateFormulas();
        }
        else if(selectedTier=='-1'){
            opp.Selected_Tier__c = '-1';
            selectedTier = '-1';
            isCustom = true;

            update opp;
            opp.recalculateFormulas();
        }
    }  
}

Example Screenshots:

After selecting Tier 2 (Working): Tier 2 (Working)

After selecting Tier 3 (Working): Tier 3 (Working)

After selecting Custom (Not Working - Labels not Present): Custom (Not working)

0

<apex:OutputField/> displays label and text, <apex:inputField/> displays the both when those are directly under <apex:pageblockSection>, here those are under <apex:repeat> tag. You can add <apex:outputLabel/> before those fields when you are using isCustom logic.

You can try out something like this:

<apex:form rendered="{!isCustom}">
    <apex:outputLabel value="{!field.Label}" />
    <apex:inputField value=" {!Opportunity[field]}" />
</apex:form>

or

<apex:form rendered="{!isCustom}">
      <apex:outputLabel value="{!$ObjectType.Opportunity.fields[field].Label}"/>
      <apex:inputField value="{!Opportunity[field]}"/>
<apex:form/>

Following generic code will return the field label

<apex:outputLabel value="{!$ObjectType.CustomObject__c.Fields.Custom_Field__c.Label}" />

  • @MorganMarch just to let you know I haven't compiled this code. Just to give you an idea to fix the issue. – Santanu Boral Jul 23 '16 at 7:14
  • Thanks for taking a stab at this. I tried your suggestion of using outputLabel but if I use {!field} it returns the API field name, not the field label... and if I use <apex:outputLabel value="{!Opportunity[field]}" /> I get back the actual value of the field for some reason (like 1.65%), instead of the label. I also tried adding .name to the end of some of the arguments but kept getting told that 'name' wasn't part of the fieldSet – Morgan Marchese Jul 23 '16 at 21:29
  • @MorganMarch updated answer to retrieve label – Santanu Boral Jul 24 '16 at 0:20
  • @MorganMarch updated code will code the issue, I have tested at my dev. Please mark and close the question. – Santanu Boral Jul 24 '16 at 0:29
  • 1
    Ahhh I got it figured out using your code as a starting point. I didn't try the longhanded approach of adding the whole {!$ObjectType.ObjectName.Fields.FieldName.Label}, but, your example made me realize I should try {!field.Label} instead of .Name. Thank you for your help! – Morgan Marchese Jul 24 '16 at 3:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.