Struts 2: updating the list of objects from a form with a managed architecture model

I have already searched and found several approaches here, but I cannot get them to work for my project.

I want to show an edit page for a list of objects that need to be updated immediately. I am using a model-based approach to achieve this, but I cannot get it to work properly. I can always display and iterate over the list and its values, but I cannot change its values.

So here is what I am doing now:

I have a Teilzeitgrad model in my database that has some simple attributes with getters and setters.

public class Teilzeitgrad { private Date datumAb; private Date datumBis; private double betrag; // ... getters and setters } 

In my Action class, I implement the ModelDriven interface with a list of Teilzeitgrad objects

 public class DienstabschnittViewJahrAction implements ModelDriven<List<Teilzeitgrad>>, Preparable { List<Teilzeitgrad> teilzeitgrads; private String tzgTypKey; private Integer jahrIndex; public String execute() { return SUCCESS; } public List<Teilzeitgrad> getModel() { if(teilzeitgrads == null) { teilzeitgrads = getTeilzeitgradListByTypAndJahr(getTzgTypKey(), getJahrIndex()); } return teilzeitgrads; } public List<Teilzeitgrad> getTeilzeitgrads() { return teilzeitgrads; } public void setTeilzeitgrads(List<Teilzeitgrad> teilzeitgrads) { this.teilzeitgrads = teilzeitgrads; } @Override public void prepare() throws Exception { // TODO Auto-generated method stub } public String getTzgTypKey() { return tzgTypKey; } public void setTzgTypKey(String tzgTypKey) { this.tzgTypKey = tzgTypKey; } public Integer getJahrIndex() { return jahrIndex; } public void setJahrIndex(Integer jahrIndex) { this.jahrIndex = jahrIndex; } } 

The action mapping in struts.xml is defined as follows:

 <action name="*/auth/GroupAdmin/processEditDienstabschnittJahr" method="execute" class="org.hocon.ul.portal.action.DienstabschnittViewJahrAction"> <result name="success" type="redirect">${referer}</result> </action> 

In my JSP file, I repeat the model object, displaying its values ​​in text fields or lists as follows:

 <ul:form action="auth/GroupAdmin/processEditDienstabschnittJahr"> <s:iterator value="model" status="rowStatus"> <tr> <td style="text-align: center;"> <s:date name="model.get(#rowStatus.index).datumAb" var="datumAb_DE" format="dd.MM.yyyy" /> <s:textfield style="width:70px;" name="model.get(#rowStatus.index).datumAb" value="%{#datumAb_DE}" label="DatumAb"></s:textfield > </td> <td style="text-align:center;"> <s:date name="model.get(#rowStatus.index).datumBis" var="datumBis_DE" format="dd.MM.yyyy" /> <s:textfield style="width:70px;" name="model.get(#rowStatus.index).datumBis" value="%{#datumBis_DE}" label="DatumBis"></s:textfield > </td> <td class="currency"> <s:set var="tzgBetrag"> <fmt:formatNumber type="NUMBER" maxFractionDigits="0"><s:property value="%{getBetrag()*100}"></s:property></fmt:formatNumber> </s:set> <s:textfield style="width:30px;" maxlength="3" name="model.get(#rowStatus.index).betrag" value="%{#tzgBetrag}" label="Betrag"></s:textfield > </td> </tr> </s:iterator> <s:submit style="width:24px; height:24px;" type="image" src="../../../res/24px/floppy-disk.png" value="Speichern"></s:submit> </ul:form> 

ul-tag is a custom taglib that adds a client url parameter to the action path.

So when I show the page, it shows all my Teilzeitgrad entries with a row for each entry. But when I submit the form, the list of my models is not populated. Setter setTeilzeitgrads(List<Teilzeitgrad> teilzeitgrads) is not even called at all. I also tried accessing the list in array syntax:

<s:textfield style="width:70px;" name="teilzeitgrads[#rowStatus.index].datumAb" value="%{#datumAb_DE}" label="DatumAb"></s:textfield >

but it also did not work.

Any help resolving this case is appreciated! Thanks in advance!

Lenzo

+4
source share
5 answers

Ok - this is a very simple working example of indexing a list. The main change is moving model creation from getModel () to prepare (). This is because getModel () is called for every value needed to set the list, so you end up recreating your model every time overwriting the previous change.

 package com.blackbox.x.actions; import java.util.ArrayList; import java.util.List; import com.blackbox.x.actions.ListDemo.ValuePair; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; import com.opensymphony.xwork2.Preparable; public class ListDemo extends ActionSupport implements ModelDriven<List<ValuePair>>, Preparable { private List<ValuePair> values; @Override public List<ValuePair> getModel() { return values; } public String execute() { for (ValuePair value: values) { System.out.println(value.getValue1() + ":" + value.getValue2()); } return SUCCESS; } public void prepare() { values = new ArrayList<ValuePair>(); values.add(new ValuePair("chalk","cheese")); values.add(new ValuePair("orange","apple")); } public class ValuePair { private String value1; private String value2; public ValuePair(String value1, String value2) { this.value1 = value1; this.value2 = value2; } public String getValue1() { return value1; } public void setValue1(String value1) { this.value1 = value1; } public String getValue2() { return value2; } public void setValue2(String value2) { this.value2 = value2; } } } 

and corresponding jsp

 <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> </head> <body> <s:form action="list-demo" theme="simple"> <table> <s:iterator value="model" status="rowStatus"> <tr> <td><s:textfield name="model[%{#rowStatus.index}].value1" value="%{model[#rowStatus.index].value1}"/></td> <td><s:textfield name="model[%{#rowStatus.index}].value2" value="%{model[#rowStatus.index].value2}"/></td> </tr> </s:iterator> </table> <s:submit/> </s:form> </body> </html> 
+2
source

You send the values ​​to model , you have to send them to your teilzeitgrads list.

For example, see http://www.dzone.com/tutorials/java/struts-2/struts-2-example/struts-2-model-driven-action-example-1.html .

Update
How about name="teilzeitgrads[%{#rowStatus.index}].datumBis" .

0
source

Have you tried this approach?

 <s:iterator var="teilzeitgrad" value="teilzeitgrads" status="listStatus"> <s:set name="paramName">teilzeitgrads[${ listStatus.index }].datumAb</s:set> <s:textfield name="%{#paramName}" value="%{#teilzeitgrad.datumAb}"/> </s:iterator> 
0
source

Assuming you have the correct configuration - the problem is probably related to how you define indexing. Try changing the name attribute in the text box to use

 model[%{#rowStatus.index}].datumBis 

and let OGNL sort the access methods. (I also used Firebug in Firefox to find out what really gets submitted when the form is submitted)

0
source

Thank you all that you like! Your tips were most helpful. I finally picked it up and started rewriting everything from scratch. Now I can edit my models using the following Action-Class:

 public class TeilzeitgradEditAction implements ModelDriven<List<Teilzeitgrad>> { List<Teilzeitgrad> teilzeitgrads; private String tzgTypKey; private Integer jahr; public String execute() { return SUCCESS; } @Override public List<Teilzeitgrad> getModel() { if(teilzeitgrads == null) { teilzeitgrads = getTeilzeitgradListByTypAndJahr(tzgTypKey, jahr); } return teilzeitgrads; } public List<Teilzeitgrad> getTeilzeitgrads() { return teilzeitgrads; } public void setTeilzeitgrads(List<Teilzeitgrad> teilzeitgrads) { this.teilzeitgrads = teilzeitgrads; } // getters and setters for local attributes } 

and this jsp code:

 <ul:form action="auth/GroupAdmin/processEditDienstabschnittJahr"> <s:iterator var="teilzeitgrad" value="teilzeitgrads" status="listStatus"> <tr> <td> <s:date name="%{#teilzeitgrad.datumAb}" var="datumAb_DE" format="dd.MM.yyyy" /> <s:textfield name="teilzeitgrads[%{#listStatus.index}].datumAb" value="%{#datumAb_DE}"/> </td> </tr> </s:iterator> <s:submit style="width:24px; height:24px;" type="image" src="../../../res/24px/floppy-disk.png" value="Speichern"></s:submit> 

Thanks so much for your support!

Cheers, Lenzo

0
source

Source: https://habr.com/ru/post/1441512/


All Articles