+ Start a Discussion
garybgaryb 

apex:variable, repeat, dynamic bindings - view state side effects?

Has anyone else had issues with using apex:variable, apex:repeat, dynamic fields, and state not being preserved when actions take place?

 

I've got the following PoC, a page and its controller. The page shows the First Name and Last Name of a contact (hard coded ID - replace it with one of your own if you're trying this at home) as inputfields. The user can make changes and click a button and the changes should save. However, they do not.

 

First the page:

 

<apex:page tabStyle="Contact" controller="TestingPageCtrl">
    <div style="margin-top:14px">
        <apex:form >
                <apex:variable var="obj" value="{!sobj}"/>
                <apex:variable var="fieldNames" value="{!fields}"/>
                <apex:pageblock>
                    <apex:pageBlockSection>
                        <apex:repeat var="fieldName" value="{!fieldNames}">    
                            <apex:inputField value="{!obj[fieldName]}"/>
                        </apex:repeat>
                    </apex:pageBlockSection>
                </apex:pageBlock>

            <div style="width:610px">
                <apex:commandButton value="Next" style="float:right;" action="{!save}" />
            </div>
        </apex:form>
    </div>
</apex:page>

 

And now, the controller:

 

public class TestingPageCtrl {

    public SObject sobj {get; set;}
    public List<String> fields {get; set;}
    
    public TestingPageCtrl() {
        System.debug('In TestingPageCtrl');
        sobj = [select ID, FirstName, LastName from Contact where ID = '003K0000009T2za'][0];
        fields = new List<String> {'FirstName', 'LastName'};
    }

    public PageReference save() {
        System.debug('In save()');
        Database.update(sobj);
        return null;
    }
}

 

In the save() method, the changes made by the user are not carried across. There are some things I've noticed:

 

  • I actually first encountered this in a custom component. Using attributes (and passing the values in from the parent page) rather than variables works - however, there is some loss of elegance in the code.
  • You'll notice I'm using a repeat to loop over strings that are field names, and they are then used with dynamic bindings so that the controller can control what fields are displayed. Removing this repeat and putting hardcoded dynamic bindings (i.e. obj['FirstName']) works. Problem here is that my code becomes a lot less re-usable.
  • Looking at the debug logs, it looks as if the deserialization is not being performed when the action takes place.

 

I don't understand why this doesn't work as it is - is there something I'm missing or doing wrong? Do people think this should work as it currently it?

 

Any feedback and input would be greatly appreciated!

 

P.S. - I'm pretty sure this is not Summer '12 related as I was having this issue on Friday night before (and after) the upgrade.

Abhay AroraAbhay Arora

Hi

In such a case you need to setRedirect(false); after your pageRef it will solve your problem

garybgaryb

I'm afraid that doesn't work. If I debug the object to the log, I can see it has its original values, not what the user entered. The redirect comes afterwards, so doesn't have an effect on the update that takes place before hand

 

You're actually right though, I do return a PageReference with setRedirect = true, but the code I posted in my original post was cobbled together as a stripped back proof of concept of what looks like might be a bug.

 

Thanks for the reply though :)

aballardaballard

That looks like it ought to work.  There have been some issues with inputField, but this is not one I've seen,   I'll try it out.

garybgaryb

Thanks aballard, let us know how you get on!

aballardaballard

For some reason it is not working with the apex:variable used to define the fields to iterate over. 

 

If you change the repeat to

 

<apex:repeat var="fieldName" value="{!fields}">

     <apex:inputField value="{!obj[fieldName]}"/>

</apex:repeat>

 

instead it seems to work as expected.  

 

I'll file a bug report for it. 

garybgaryb

Thanks abllard. Are you an SFDC engineer and able to raise this in the way you need to? If so, let me know if there's anything I can do to provide more information; if not, again, let me know and I'll raise my own case so at least there will be two tickets for the same issue.

aballardaballard

I'm anSFDC engineer, but you should open a support case anyway.   Bugs with customer cases get a higher priority than ones opened internally.... 

 

If you open a case, tell them to link it to bug W-1271484  . 

garybgaryb

Done - case number 07591974.

 

Thanks for looking into it and commenting!