Search code examples
validationstruts2ognlrepopulation

Struts2 OGNL runtime expression


I am validating list of objects. In order to show users what they typed wrong, I need to repopulate fields on conversion error. I read that in order to repopulate fields value on page I need to do something like this:

<s:textfield name="user.name" value="%{user.name}"/>

For repopulating array, I must refer to them through indices. As mentioned here: update a list of value in textfield in struts2

I have a list of Users, that I need to validate. I have my own index counter on iterator for specific reason.

<s:set name="counter" value="0"/>
<s:iterator value="users" var="user">
   <s:textfield name="users[%{#counter}].birthdate" value="%{users[#counter].birthdate}"/>
   <s:set name="counter" value ="%{#counter + 1}"/>
</s:iterator>

I am using visitor validator for object User.

<field name="birthdate">
    <field-validator type="conversion">
        <param name="repopulateField">true</param>
            <message>${getText("E011", {"birthdate"})}</message>
    </field-validator>
</field>

As I said, I am not using iterator index counter for specific reason.

The problem is this value="%{users[#counter].birthdate}" part is not working. If I change counter to 0 it repopulates the value of users[0].birthdate right. Seems like it is not getting value of counter in OGNL expression.

I tried with:

value="%{users[counter].birthdate}"
value="%{users[%{#counter}].birthdate}"
...
and so on.

Can somebody help me to make this work?

UPDATE

It ended up that I should have mentioned my special case:

<s:iterator value="users" var="user" status="status">
  <s:if test="#status.index != removeIndex">

I found out that I don't need to specify value for field name for it to repopulate values. But I needed to use that because of this line:

<s:if test="#status.index != removeIndex">

It will take lots of my English effort to explain why you guys misunderstood me. Can we delete this post?. Thanks


Solution

  • It's better if you ask how to do something... rather than say you have a reason for doing it this way and of course this way isn't working. It gives me a headache...

    I don't understand this...

    <s:set name="counter" value="0"/>
    <s:iterator value="users" var="user">
       <s:textfield name="users[%{#counter}].birthdate" value="{users[counter].birthdate}"/>
       <s:set name="counter" value ="%{#counter + 1}"/>
    </s:iterator>
    

    I'll rewrite (without testing) what I think you mean...

    <s:iterator value="users">
       <s:textfield name="users.birthdate" value="birthdate"/>
    </s:iterator>
    

    The above requires that the following conditions be met... a) That "users" is a list of type "User" and b) that the struts2 conversion framework has been told that users is a list of type "User" which is as simple as adding an annotation like so: http://struts.apache.org/2.3.1.2/docs/keyproperty-annotation.html

    With those conditions met... Send as many at one time without the mess of needing to use array notation and you can repopulate the fields.

    Now, why would you expect the form values to repopulate after it failed to submit? That is how are you using validation? If for some reason you aren't you have created some action mapping on a value of INPUT or ERROR to direct back to the input page (kind of a waste of effort when the validation framework exists).