[SalesForce] Only rerender row in using

I have an editable page block table displaying SObjects records per row. There are also actions per row that only modify the row's record.

<apex:pageBlockTable>
    <apex:column><apex:commandButton action="{!doRowAction}"/></apex:column>
    <apex:column/>
    <apex:column/>
</apex:pageBlockTable>

To reduce loading time and prevent irrelevant validation errors (those of other rows) I want to restrict the rerendering to a single row.

<apex:pageBlockTable>
    <apex:actionRegion renderRegionOnly="true">
        <apex:column><apex:commandButton action="{!doRowAction}"/></apex:column>
        <apex:column/>
        <apex:column/>
   </apex:actionRegion
</apex:pageBlockTable>

The problem is this doesn't save!

Error: <apex:column> must be the direct child of either
<apex:dataTable> or <apex:pageBlockTable>

Edit: We also tried to rebuild the table in plain HTML using apex:repeat but ran it another yet unsolved problem.

Best Answer

I found a way to rerender the rows while only processing the row you're on. I will try to outline the concept here but a a full description of my solution can be found here:

Visualforce: Dynamically ReRender a row within <apex:repeat> by passing $Component through controller

Clarify Action Region:

As you probably already realize, the actionRegion tag will focus your form to only process the fields contained by it, "it does not define what area(s) of the page are re-rendered when the request completes". I personally didn't have this requirement.

Action Function Approach:

I am unsure what you expect the user experience to be like, in my example the values bound to the controller are updated every time the user makes a change to the inputText using the onchange event to trigger an actionFunction. In this instance I iterated through my repeat with a map (3 levels deep) and dynamically passed the map indexes so that my controller could figure out which "row" of data to set/process.

Example of operations:

  1. Form Markup:

    <apex:inputText onChange="jsMethod(this)">

  2. JS Function:

    jsMethod(row){ actionMethod(params) }

  3. VF Action Function:

    <apex:actionFunction action="{!ctrlCustomSetter}" rerender="{!$Component.myRepeater.myRowId}" />

  4. Controller PageReference Method:

    PageReference ctrlCustomSetter(){ String var = String.valueOf(ApexPages.currentPage().getParameters().get('myvar')); }

Command Button Approach:

You could however use an actionSupport on your command button to also pass the indexes to your controller. Depending on your user interaction you may need some jQuery to set those parameters, but I find its much easier manipulate my list of data as the user interacts with it (onChange) and then just process the data on submission.

Now the key to rerendering the rows and not the complete container is to generate the component id in the rerender attribute, you cannot "pass" the value through a controller variable like so: rerender="{!rowID}", this will not work. Rather select the component you want like so:

rerender="{!$Component.myRepeaterId.myRowId}"

I am not 100% this answer meets your requirements but I believe there is overlap with both of our issues so I felt it was worth posting in case it helps you at all (hopefully it doesn't get scrutinized too much). Good Luck!

Related Topic