2

I have a VisualForce page which, under "normal" circumstances, upon submission, via the custom controller extension, inserts a record.

But sometimes, as it should, it does not insert the record, but instead displays an error message to the user saying why the record was not saved.

This message, as desired, is displayed above the form.

However -- and this is the undesirable part -- the form has also now been cleared, whereas I would prefer that the values were repopulated so they can be corrected.

Is there a good/easy way to do this?

Here is the VisualForce Page:

    <apex:page standardController="Player__c" extensions="RF_PlayerTechnologyOrderFormVFCtrlExt" tabStyle="Player__c"  showHeader="false" sidebar="false" docType="html-5.0">

    <apex:form >
        <apex:pageBlock title="Technology Order Form" rendered="{!hasAvailableTechnology}">
            <apex:messages style="font-weight:bold; color:red;" />
            <apex:outputPanel rendered="{!successMessage!=null}" style="font-weight:bold; color:green; text-align:center;" >
                <p>{!successMessage}</p>
            </apex:outputPanel><br/>

            <apex:outputLabel for="TechnologySelectionTable">Select a technology to invest in:</apex:outputLabel>
            <!-- @see: http://www.eltoro.it/ArticleViewer?id=a07A000000NPRidIAH --> 
            <apex:pageBlockTable id="TechnologySelectionTable" value="{!availableTechnologySelectOptionRowList}" var="availableTechnologySelectOptionRow">
                <apex:column >
                    <input type="radio" name="Technology" value="{!availableTechnologySelectOptionRow.id}" onClick="roboForceApp.changeRow(this, '{!$Component.TechnologyInvestmentIdValue}');" />
                </apex:column>
                <apex:column headerValue="Technology"            value="{!availableTechnologySelectOptionRow.name}" style="font-weight: bold;"/>
                <apex:column headerValue="Description"           value="{!availableTechnologySelectOptionRow.description}" />
                <apex:column headerValue="Development Manhours"  value="{!availableTechnologySelectOptionRow.developmentManhours}" />
                <apex:column headerValue="Upfront Cost"          value="{!availableTechnologySelectOptionRow.upfrontCost}" />
                <apex:column headerValue="Monthly Cost"          value="{!availableTechnologySelectOptionRow.monthlyCost}" />
            </apex:pageBlockTable>  
            <apex:inputHidden id="TechnologyInvestmentIdValue" value="{!selectedTechnology}"/> 
            <br/>           

            <table>
                <tr title="Lowering this value may cause Pending Investments to be deprioritized." >
                    <th><apex:outputLabel for="priorityValue" >Priority Value: </apex:outputLabel></th>
                    <td><apex:input id="priorityValue" type="number" value="{!priorityValue}" /></td>
                </tr>
                <tr title="If this box is checked, RoboForce will queue you order even if you may not have enough money to pay for it." >
                    <th><apex:outputLabel for="ignoreLiquidity">Ignore Liquidity</apex:outputLabel></th>
                    <td><apex:inputCheckbox id="ignoreLiquidity" value="{!ignoreLiquidity}"/></td>
                </tr>
            </table>    

            <apex:pageBlockButtons location="bottom">
                <apex:commandButton action="{!Order}" value="Order"/>
            </apex:pageBlockButtons>
        </apex:pageBlock>  

    </apex:form>

    <apex:pageBlock title="No Technology Available" rendered="{!!hasAvailableTechnology}">
        <p>
            You do not meet the requirements to develope any additional technologies.
        </p>
    </apex:pageBlock>

    <apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"/>
    <script>
        var roboForceApp = roboForceApp || {};

        roboForceApp.changeRow = function (input, textId)
        {
            $("[id$='TechnologyInvestmentIdValue']").val(input.value);
        }
    </script>

</apex:page>

Here is the controller extension:

 public with sharing class RF_PlayerTechnologyOrderFormVFCtrlExt extends RF_PlayerVFCtrlExt   
{
    RF_PlayerOrderFormVFCtrlInvestmentCache       investmentCache;
    RF_PlayerVFCtrlPlayerInvestmentCache          playerInvestmentCache; 

    public RF_PlayerTechnologyOrderFormVFCtrlExt(
                                                    ApexPages.StandardController standardController, 
                                                    RF_PlayerOrderFormVFCtrlInvestmentCache           investmentCache, 
                                                    RF_PlayerVFCtrlPlayerInvestmentCache     playerInvestmentCache
                                                )
    {
        super(standardController);
        this.investmentCache       = investmentCache;
        this.playerInvestmentCache = playerInvestmentCache;
    }

    public RF_PlayerTechnologyOrderFormVFCtrlExt(ApexPages.StandardController standardController) 
    {
        this(standardController, new RF_PlayerOrderFormVFCtrlInvestmentCache(), new RF_PlayerVFCtrlPlayerInvestmentCache());
    }

    public String selectedTechnology { get; set; }

    public Boolean getHasAvailableTechnology()
    {
        return ((availableTechnologySelectOptionRowList != null) && (!availableTechnologySelectOptionRowList.isEmpty()));
    }

    public List<RF_InvestmentSelectOptionRow> availableTechnologySelectOptionRowList
    {
        get
        {
            if (availableTechnologySelectOptionRowList == null)
            {
                availableTechnologySelectOptionRowList = new List<RF_InvestmentSelectOptionRow>();
                for (Investment__c availableTechnology : availableTechnologyByIdMap.values())
                {
                    availableTechnologySelectOptionRowList.add(new RF_InvestmentSelectOptionRow(availableTechnology));
                }
            }
            return availableTechnologySelectOptionRowList;
        }
        private set;
    }

    private Map<Id, Investment__c> availableTechnologyByIdMap
    {
        get
        {
            if (availableTechnologyByIdMap == null)
            {
                availableTechnologyByIdMap = new Map<Id, Investment__c>(investmentCache.getAvailableList(player.id, RF_InvestmentRecordTypeHelper.RECORDTYPE_TECHNOLOGY_ID, possessedInvestmentIdSet));
            } 
            return availableTechnologyByIdMap;
        }
        set;
    }

    private Set<Id> possessedInvestmentIdSet
    {
        get
        {
            if (possessedInvestmentIdSet == null)
            {
                List<Player_Investment__c> possessedInvestmentList = playerInvestmentCache.getPlayerList(player.id);
                possessedInvestmentIdSet = UTIL_SetHelper.buildIdSet(possessedInvestmentList, 'investment__c', true); 
            }
            return possessedInvestmentIdSet;
        }
        set;
    }

    public Integer priorityValue
    {
        get
        {
                if (priorityValue == null)
                {
                    priorityValue = ((player.Lowest_Assigned_Priority__c == null) || (player.Lowest_Assigned_Priority__c < 1))
                                  ? 1
                                  : ((Integer) player.Lowest_Assigned_Priority__c + 1);
                }
                return priorityValue;
        }
        set;
    }

    public Boolean ignoreLiquidity { get; set; }

    public String successMessage 
    { 
        get
        {
            if (ApexPages.currentPage().getParameters().get('successMessage') != null)
            {
                successMessage = ApexPages.currentPage().getParameters().get('successMessage');
            }

            if (String.isBlank(successMessage)){ successMessage = null; }               

            return successMessage;
        } 
        private set; 
    }

    public void order()
    {
        Player_Pending_Investment__c newPlayerInvestment = new Player_Pending_Investment__c
            (
                player__c           = player.id,
                investment__c       = selectedTechnology,
                priority__c         = priorityValue,
                ignore_liquidity__c = ignoreLiquidity,
                status__c           = RF_PlayerPendingInvestmentHelper.STATUS_OPEN 
            ); 

        Boolean isPending = true;               
        try {  insert newPlayerInvestment; } 
        catch (DmlException ex)
        {
            ApexPages.Message message = new ApexPages.Message(ApexPages.Severity.ERROR, ex.getDmlMessage(0));
            ApexPages.addMessage(message);
            isPending = false;
            ApexPages.currentPage().getParameters().put('successMessage', ''); 
        }

        if (isPending) 
        { 
            successMessage = availableTechnologyByIdMap.get(selectedTechnology).name + ' has been ordered successfully.';
            ApexPages.currentPage().getParameters().put('successMessage', successMessage); 

            //  FIXME: Clear these on successful submission so options will be reevaluated
            investmentCache.reset(player.id);               
            availableTechnologyByIdMap             = null;
            availableTechnologySelectOptionRowList = null;
        } 

    }

}
  • 3
    Can you post your code for the page and controller? There is a way to do it, and it would be easier to see your code to give a recommendation. – Daniel Hoechst Dec 8 '14 at 16:54
  • @DanielHoechst, As you may have noticed, I've posted the code above... I am looking forward to your suggestion. – Brian Kessler Dec 11 '14 at 9:13
  • It looks like you've got a radio button, an integer input and a checkbox input. Are all three getting cleared out on error? – Daniel Hoechst Dec 11 '14 at 15:11
  • @DanielHoechst, now that you mention it, the problem only seems to be with the radio button. The integer does not reset to default; if the box is checked, the error cannot occur. – Brian Kessler Dec 11 '14 at 15:15
  • 1
    Hmm, I haven't done much with radio buttons like that. My guess is that the selected value is still in the hidden field. Maybe you can use JavaScript to select the correct one? – Daniel Hoechst Dec 11 '14 at 16:11
0

NOTE: Salesforce.stackexchange.com presently seems buggy. The complete text with correct layout is the editor, but won't display correctly neither in preview nor upon submission. I don't know how to fix this!

There wasn't quite an "easy way", but thanks to @Daniel Hoechst, I was able to figure out the solution which required three essential changes to my code:

  1. I need to update my VisualForce controller to more intelligently return the value for getAvailableInvestmentSelectOptionRowList():

    public List availableInvestmentSelectOptionRowList { get { if (availableInvestmentSelectOptionRowList == null) { availableInvestmentSelectOptionRowList = new List(); for (Investment__c availableInvestment : availableInvestmentByIdMap.values()) { availableInvestmentSelectOptionRowList.add(new RF_InvestmentSelectOptionRow(availableInvestment)); } } else if (!String.isBlank(selectedInvestmentId)) { for (RF_InvestmentSelectOptionRow availableInvestmentSelectOptionRow : availableInvestmentSelectOptionRowList) { if ((String.valueOf(availableInvestmentSelectOptionRow.getId()).equals(selectedInvestmentId))) { availableInvestmentSelectOptionRow.isChecked = true; break; } } }

    return availableInvestmentSelectOptionRowList;
    

    } private set; }

  2. I needed to add the following code into my RF_InvestmentSelectOptionRow (which is mostly a wrapper for Investment__c):

    public String getRadioButton()
    

    { return ''; }

    private String getChecked() { return ((isChecked != null) && isChecked) ? 'checked="checked"' : ''; }

This is mostly necessary because the HTML specification for checked is not something logical like checked="true" vs. checked="false", but rather the value is checked if the attribute is simply present (with no value assignment) or if the value is checked="checked". The behaviour of checked="false" or checked="unchecked" is undefined. SFDC's XML/VF parser won't accept putting anything into the middle of an element which does not fit the attributeName="attributeValue" format, so we can't just put {!investmentSelectOptionRow.checked} into the element on the VF page.

  1. Change the VF to include the radio button to:

We need the

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.