[SalesForce] How to circumvent validation without using immediate=true

I have a VF page that is used as override page for New and Edit of CustomObject__c. On this page the user can also create and edit child records. All of them are rendered editable in the pageblock table below. Next to each input field there is a button to copy down its value to the fields below.

    <apex:pageBlockTable value="{!rows}" var="row" id="pbTable" >

        <apex:repeat value="{!fields}" var="field">
            <apex:column headerValue="{!field.Label}"> 

                    <apex:inputField value="{!row.record[field]}" />

                    <apex:commandlink action="{!doCopyDown}" title="Copy value down" rerender="pbTable">  
                        <apex:image value="{!$Resource.copy_button_png}" />

                        <apex:param name="selectedRow" assignTo="{!selectedRow}" value="{!row.index}" />
                        <apex:param name="selectedField" assignTo="{!selectedField}" value="{!field}" />
                    </apex:commandlink>

            </apex:column>
        </apex:repeat>
    </apex:pageBlockTable>

Clicking it calls the a action method below:

public with sharing class MyCtrl {

    public Integer selectedRow { get; set; }
    public String selectedField { get; set; }
    public List<SObjectRow> rows { get; private set; }

    ...

    public PageReference doCopyDown() {
        SObjectRow sourceRow = null;

        for(SObjectRow row : rows) {
            if(row.index == selectedRow) {
                sourceRow = row;
            }
            else if(row.index > selectedRow) {
                Object newValue = sourceRow.record.get(selectedField);
                row.record.put(selectedField, newValue);
            }
        }

        return null;
    }
}

My problem is that the copy code is not called if any validation rule fails (e.g. field is blank).
enter image description here

If I otherwise add an immediate="true" to surpass validation it also doesn't work, as the server code knows nothing of the value the user has just entered into the source field. Immediate = true seems not to update the model on the server.

Any way to solve this? Maybe using apex:actionRegions?!

Best Answer

It looks like the fields you want to populate are themselves required, so you're trying to submit required, blank fields and have them populated by the back end. If that's true, you can't do it except with immediate="true". And as you say then the setters don't run so you have no values.

Wrapping them in <apex:actionRegion /> won't help as they're still going back to the server blank, which is the problem. Action regions can help when you a bunch of fields you don't want to be validated in one area of the VF, and you want to submit a different area for your action.

You can try

  • populating them front end using js
  • keeping your action as immediate but passing the field values back to it in <apex:param />. You'd probably need JS for that too, to populate the params from the screen input fields.

I'd do it front end, if it didn't include adding new items to the list. I've never tried to use front end javascript to add new items to a list, but the idea of using something like JS Remoting and then redrawing the screen seems like it would take a long time and possibly not work anyway.