You need to sign in to do that
Don't have an account?
Setter for Lists
I have a VF page that uses an apex:repeat block with inputFields and actionSupport. If the action is fired the data is transmitted to the controller. So from that point of view everything is fine.
However I'd like to do some work in the setter, checking if some special fields are changed in fact.
See this very simple example that illustrates the problem
public with sharing class Testing {
public List<Account> values
{
get
{
System.debug('GETTER' + this.values);
return this.values;
}
set
{
System.debug('SETTER' + value);
// never get to this point!!!
this.values = value;
}
}
public String inputValue { get; set; }
public String outputValue { get; set; }
public Testing()
{
System.debug('Start Testing class');
/*
values = new List<String>();
values.add('One');
values.add('Two');
values.add('Three');
*/
values = [Select Id, Name from Account limit 3];
}
public PageReference dblClickAction()
{
System.debug('dblClickAction(): inputValue -> ' + inputValue);
System.debug('dblClickAction(): outputValue -> ' + outputValue);
System.debug('dblClickAction(): values -> ' + values);
//inputValue = outputValue;
return null;
}
}
And this is my VF page
<apex:page controller="Testing">
<apex:form >
<apex:pageBlock id="pBlock">
<apex:repeat value="{!values}" var="val">
<apex:outputText value="{!val.Name}" />
<apex:actionRegion >
<apex:inputText value="{!val.Name}">
<apex:actionSupport action="{!dblClickAction}" rerender="pBlock" event="onchange">
<apex:param assignTo="{!inputValue}" name="inputValue" value="{!val.Name}" />
</apex:actionSupport>
</apex:inputText>
<br />
</apex:actionRegion>
</apex:repeat>
</apex:pageBlock>
</apex:form>
</apex:page>
What happens is that the getter of 'values' is called and the 'onchange' event fires perfectly. The rerender renders the new value of the field in the 'outputText'. Fine, BUT the setter of 'values' is never called and I'd like to do some comparison of the record returned with the actual one before setting the new one.
So I have no clue HOW the value is set in fact.
TIA
DerGrobe
Hi,
The values is only used in the first time when the constructor start and its working. ( see below debug log )
everytime you change the inputtext it wont change the value of the 'Values' hence you wont see any debug inside the setter .
Hope it can clarify your doubt.
My question is why the setter isn't called when the onchange event fires. If I change the content of inputText the onchange is fired and the values is updated in the controller, but the setter isn't called. So how does it get updated?
Initial call when entering the page, everything is totally clear.
When changing the value the onchange fires and the setter is not called, although the changed values are set.
You see that the first call to the getter holds the old value 20091216081617.022:Class.Testing: line 31, column 13: GETTER(Account:{Name=GMS and on 2nd call 20091216081617.022:Class.Testing: line 31, column 13: GETTER(Account:{Name=GMS2 the value is updated.
So when and how is it updated? I'd like add some code to the setter that is doing that which is obviously not the setter in my code.
TIA
Your setter isn't called because you don't have an input field backed by the list itself. What you have done is to iterate a list and create a number of input fields that are backed by the name field of each account.
When the value of the input field is changed, the setter for the name field of the appropriate account object is fired, which is not in your code and thus you don't see it.
When I've been doing similar work to this, I normally pass the id of the object through to the action method, and then extract the object from the list. However, I suspect that you will find that the account name has been changed due to the binding before your action method fires.
ok, understand that.
but i'm not able to create an appropriate setter for this, how should it be named? i wasn't able to find any documentation for it unfortunately.
exactly, the account name is already changed at that point, i checked that out first.
The setter already exists - it is part of the Account sObject and allows the Name field to be changed.
If you want to intercept this change, you'll have to write a wrapper class for Account and provide a getter/setter for the wrapped name field. Then populate your list with wrapper classes rather than the accounts. That way your setter will be called when the value is changed, as its your object that will be backing it.
You'll have to change your input backing variable to use the wrapped class getter. Also, the inputfield component will need to change to an inputtext, as you will no longer be backing the input with an sobject field.
ah, ok, so some kind of "hidden magic". thanks for the info.
i'll check out the wrapper-class approach for my simple example and then decide if it's feasible for larger objects or if maybe setting an "prevAccount" variable it easier to handle.