How can I dynamically render required fields using a Dynamic Component

Background

I have a Visualforce page on which I am rendering a lot of fields using a Dynamic Component (which is an Output Panel that contains all of the fields). The fields are added based on a selection of options in a multipicklist, and each time a selection is made in the multipicklist, the page is re-rendered from the server side to display the new selection of fields. Some of these fields need to be required.

Issue

Whenever a field is required on the page and the selection is changed in the mutipicklist that controls which fields are rendered, Visualforce throws an error that the field has not been filled in, even if it is to be removed based on the selection. This prevents the field from being removed, and the fields on the page don’t get updated because of that Visualforce error.

Idea

So, I had the idea to create my own required functionality using jQuery and JavaScript to validate on the client side with a validation method in Apex on the server side.

Question

Is there a better way to do this? If not, how can I duplicate Visualforce’s “required” functionality (displaying a red bar next to each of the required fields).

For Reference

Here’s a portion of my current Visualforce Page. Products is a multipicklist; whenever the Command Button is clicked, the fields are rerendered.

<apex:pageblocksection columns="1" title="Products" id="ProductSelection" >
    <apex:inputfield value="{!Order.Product__c}" id="Products" />
    <apex:commandbutton value="Select Product" action="{!SelectProduct}" />
</apex:pageblocksection>

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

The SelectProduct method is extremely simple. It’s just a method that does nothing and returns nothing. Mainly it’s used to just perform a round trip to the server to rerender the SectionsAndFields property. For a code sample of the SectionsAndFields property, check out this answer from another question.

public void SelectProduct() { }

Answer

Looks like you’re after a partial form submission?

Try wrapping the piece you want (both the multiplicklist and the onchange or whatever you have there) in <apex:actionRegion>. As long as the region won’t cover any blank mandatory field you should be fine.

The part you rerender can be outside of said region.

<apex:page standardController="Opportunity">
<apex:form>
    <apex:pageBlock title="Master">
        <apex:pageBlockSection title="So many required fields...">
            <apex:inputField value="{!Opportunity.Name}" />
            <apex:inputField value="{!Opportunity.AccountId}" />
            <apex:inputField value="{!Opportunity.StageName}" />
            <apex:inputField value="{!Opportunity.CloseDate}" />
        </apex:pageBlockSection>
        <apex:pageBlockSection title="lets ignore them ;)">
            <apex:actionRegion>
                <apex:inputField label="Type something" value="{!Opportunity.NextStep}">
                    <apex:actionSupport event="onchange" rerender="output" />
                </apex:inputField>
            </apex:actionRegion>
        </apex:pageBlockSection>
    </apex:pageBlock>
    <apex:pageBlock title="Slave: {!Opportunity.NextStep}" id="output">
        <p>This should work even though we're in same form and all required fields will be blank</p>
        <apex:iframe src="/search/SearchResults?sbstr={!URLENCODE(Opportunity.NextStep)}&isdtp=vw" 
            rendered="{!NOT(ISBLANK(Opportunity.NextStep))}" height="500px" />
    </apex:pageBlock>
</apex:form>
</apex:page>

form submission results


Edit after code sample was provided…

If SelectProduct() is used only as a round-trip then you truly don’t need it. It’s perfectly fine to have an actionSupport (like I did) or commandButton that doesn’t have “action” param…

What happens when you try this?

<apex:pageblocksection columns="1" title="Products" id="ProductSelection" >
    <apex:actionRegion>
        <apex:inputfield value="{!Order.Product__c}" id="Products" />
        <apex:commandbutton value="Select Product" rerender="output" />
    </apex:actionRegion>
</apex:pageblocksection>

<apex:outputPanel id="output">
    <apex:dynamicComponent componentValue="{!SectionsAndFields}" />
</apex:outputPanel>

Attribution
Source : Link , Question Author : Matt K , Answer Author : eyescream

Leave a Comment