I am browsing some Struts 2 code and I see this syntax for submit button that I haven't seen before..
<s:submit key="map.keyName$Value" />
It's not working (it was working with Struts 2.0.x now we have moved to Struts 2.2.3) any more. I mean its not setting the appropriate value based on the mentioned key in the map.
Has anyone used this syntax before?
Any other alternative syntax suggestions that will let me SET values in a map (using struts tag only) will be most welcome.
The jsp page containing this code is designed to be a decoupled component that can be included by any page at runtime that's why this page CANNOT call any java code to set these values in java map - which is why i am looking for tag solution that can set values in the map.
thanks in advance
Set value in a map by :
In JSP only
OGNL assignment statement :
<s:set var="" value="map[key] = keyValue" />
Java
<s:set var="" value="map.put(key, keyValue)" />
EDIT
You could set value in map (to action class) with
<s:hidden name="map[key]" value="keyValue" />
by submit button with onclick attribute, for example (answer - assume multiple submit button) :
<script type="text/javascript">
function setMap(key, keyValue) {
document.getElementById("mapToSet").name="map['" + key + "']";
document.getElementById("mapToSet").value=keyValue;
}
</script>
<s:hidden name="test" id="mapToSet" />
<s:submit value="Search" onclick="setMap(key, keyValue)" />
I found this page when searching for "how to set values in a map in Struts2" and it led me to the following answer (which I understand is a little OT):
As an HTML input element:
<input type="hidden" name="myField[105]" value="myValue" />
This would populate an action variable declared as:
Map<Integer, String> myField;
such that:
myField.get(105).equals("myValue"); // == true
Related
I have two classes one is Action class MyAction and other is POJO class User. Inside MyAction, i have made getter-setter for User class.
Then I have index.jsp page for user input. In this, I am using struts 2 push tag for the properties stored in User class. It looks something like this:
<s:form action="go" method="post">
<s:push value="user">
<s:textfield name="id" label="usr-id"/> <!-- user.id -->
<s:textfield name="fname" label="first-name"/> <!-- user.fname -->
</s:push>
<s:submit/>
<s:token/>
</s:form>
But I am getting an error. If I remove the push tag and prefix the User properties with user, then it runs fine. Can any one guide me, where I am wrong and how to use push tag for input fields in form.
No matter if you use <s:push>, <s:set/>, <s:iterator> with its var or IteratorStatus attributes... :
to show a value, any way is a good way;
to send a value, the only way is specifying the full "path" in the name attribute.
For example, you can use the pushed object in the value attribute, but to make it work when submitting, you still need to put the user in name attribute:
<s:push value="user">
<s:textfield name="user.id" value="id" /> <!-- user.id -->
<s:textfield name="user.fname" value="fname"/> <!-- user.fname -->
</s:push>
This makes the use of <s:push> in your case totally useless.
But in an use-case where source and destination differs, eg. you read user.fname from ActionSource, and send its value to ActionDestination in a selectedFname String, the jsp would be
<s:push value="user">
<s:textfield name="selectedId" value="id" /> <!-- user.id -->
<s:textfield name="selectedFname" value="fname"/> <!-- user.fname -->
</s:push>
So it would have done "something usefull".
But basing on my experience, you won't pretty much never use push. If you need it, your data structure is probably too complex.
Your code looks like ok, but to send values from textfields you need to push the user object to the stack again. Better do it with some interceptor before the params interceptor populates the action. The same thing is doing modelDriven interceptor.
The Model-Driven interceptor watches for ModelDriven actions and adds the action's model on top of the value stack.
Note: The ModelDrivenInterceptor must come before the both StaticParametersInterceptor and ParametersInterceptor if you want the parameters to be applied to the model.
Note: The ModelDrivenInterceptor will only push the model into the stack when the model is not null, else it will be ignored.
You can use model driven approach it's pushing a model for the view and for the controller. The last is missing from your code.
The example of using ModelDriven approach.
Push is not a ui tag. Push is used for put objects into top of value stack. If your object is not in top of stack you get your values by using object.attributname. If your object is in the value stack, you can access it directly attributename.
I use Liferay 6.2 on JBoss 7.1.1.
Also I am using a JSP as view with AlloyUI.
I want a button as a link and as a submitter of a value to a method in the MVCPortlet class.
The link is inside a java array.
The attribute that is passed to the java method is inside a input field.
It works if I use just one of this two.
I tried to combine them but it doesn't work.
I tried this:
<a href="<%=unread[i][k]%>" target="_blank" >
<aui:button type="submit" />
</a>
It calls the method but it doesnt opens a new tab in my browser. In my browser I can see that it is a link, if I click right on it -> new tab, it opens it correctly in a new tab. But not if I just click on the button.
Second way:
<aui:button type="submit" onclick="window.open('http://www.google.de', '_blank', ''); return false;"/>
It just opens google but doesn't calls the method. Also it is not possible to get an Java attribute inside of a Javascript, but I could get the value out of a hidden input field. But still there would be the problem that it doesn't call the method.
I decided to get on with the second solution.
The first mistake was return false; in my onclick param, so I deleted it.
Then the submit function works as usual.
The next problem was to access a Java variable inside the javascript onclick method, so I used EL and JSTL to get it work:
<c:set var="url" scope="session" value="<%=unread[i][k]%>"/>
<aui:button type="submit" onclick="window.open('${url}', '_blank', '');" />
I am using ApplicationAware in my struts 2.0 action class. So, i placed an entry in then application map as
application.put("animalDTO", animalDTO);
animalDTO:
public class AnimalDTO {
private String name_N1;
private String name_N2;
private String name_N3;
private String name_N4;
// getters and setters
}
Now before going to my jsp page i am populating the values in each of the variables.
In JSP page: i am using iterator to get N1, N2 till N4.
Now i need to create s:textfield and populate these variables content DYNAMICALLY.
ie.
<s:iterator value="application.nameList" var="nameList">
<s:textfield theme="simple" value="%{application.animalDTO.name_#nameList}" />
</s:iterator>
Here, i am not getting any values populated.
If i hard code as -> value="%{application.animalDTO.**name_N1**}"
Then all the text-fields will be populated with value of name_N1, but that not what i need. I need for fetch the values dynamically.
Can anyone help me with this OGNL requirement?
Thanks in advance
=====================
I tried this also, i created string variable which is of the required ognl format, but i dont know how to make the string as a lookup to valuestack. This is what i did:
<s:iterator value="application.nameList" var="nameList">
<s:set var="varUrl" value="%{'application.animalDTO.name_' + #nameList}" />
<s:property value="varUrl" />
<s:textfield name="NAME__%{#nameList}" theme="simple" id="NAME-%{#nameList}" value="%{varUrl}" />
</s:iterator>
but instead the text box is getting values like:
application.animalDTO.name_1
application.animalDTO.name_2
application.animalDTO.name_3
application.animalDTO.name_4
what is need is the values corresponding to these variables.
Any idea how to convert this string as an object/key to lookup into valuestack.
Finally i got the solution. I tried many trail and error methods. And finally hit the answers. We can dynamically read the property values by doing:
<s:iterator value="application.nameList" var="nameList">
<s:textfield theme="simple" value="%{application.animalDTO['name_' + #nameList]}" />
</s:iterator>
I tried %{application.animalDTO['name_' + #nameList]} and it worked. :-)
I'm using Struts2 to display the contents of a list of objects on a JSP.
The flow of events is as following:
GetDataAction.java -> fetches values from
the database, fills in the ArrayList
named tableList. On success, the
displayData.jsp is shown.
displayData.jsp -> uses the s:iterate tag to display the values of objects
in the tableList.
The user changes some values in the
displayData.jsp and presses on the
Update button. On the click of
Update button, the
UpdateDataAction.java is called.
Now my problem is; How do I use the same tableList in UpdateDataAction.java to get the modified values?
I tried declaring an ArrayList with the same name 'tableList' (along with getters and setters), in UpdateDataAction.java but it throws a NullPointerException.
Please suggest.
IMO the way you are updating is not a good idea.Either you should link every row to a seperate edit page or use ajax.There are many plugins available to update table values using ajax,If you need i can provide you the links
Back to your way of doing it,i guess you are doing it as follows
<s:form action="UpdateDataActionName">
<s:iterator value="tableList">
<s:textfield name="objectName.propertyName1" value="%(propertyName1)">
<s:textfield name="objectName.propertyName2" value="%(propertyName2)">
<s:textfield name="objectName.propertyName3" value="%(propertyName3)">
</s:iterator>
<s:submit value="Update"/>
</s:form>
Now declare a list in your UpdateDataAction,of type <objectNameoftableListType> i.e. the same object type which the tabeList is representing.The name of the list must be objectName.Try to Iteate and check if you are getting the right values as submitted from the jsp.
Modifying working form with one spot per order to multiple spots per order I met problems with prepopulating h:selectOneMenu. Exception is java.lang.IllegalArgumentException: Value binding '#{spot.deliveryTypes}'of UISelectItems with component-path {Component-Path : [Class: javax.faces.component.UIViewRoot,ViewId: /order.jsp][Class: javax.faces.component.html.HtmlForm,Id: pf][Class: javax.faces.component.html.HtmlSelectOneMenu,Id: _idJsp11][Class: javax.faces.component.UISelectItems,Id: _idJsp12]} does not reference an Object of type SelectItem, SelectItem[], Collection or Map but of type : null
old working JSP code:
<h:selectOneMenu value="#{order.deliveryType}" immediate="true">
<f:selectItems value="#{order.deliveryTypes}" />
</h:selectOneMenu>
new not working JSP code:
<c:forEach var="spot" items="${order.spots}">
<h:selectOneMenu value="#{spot.deliveryType}" immediate="true">
<f:selectItems value="#{spot.deliveryTypes}" /> <%-- Works as empty list if this line removed --%>
</h:selectOneMenu> <c:out value="${spot.name}"/><br/>
</c:forEach>
New field was introduced List<Spot> spots as well as getter and setter. List<SelectItem> getDeliveryTypes() has been moved from managed bean class Order to class Spot.
How to access to spot.deliveryTypes? Changing # to $ didn't help because value= doesn't accept EL.
MyFaces 1.1.8
Thanks.
JSTL and JSF doesn't go nicely hand in hand. The JSP won't be processed from top to bottom as you'd expect from the coding. It's more so that JSTL processes the JSP from top to bottom first and then hands the generated result over to JSF for its own processing from top to bottom. This makes especially the c:forEach unusable for this kind of requirements. In this particular case, the ${spot} won't be there anymore when it's JSF's turn to process the JSP page.
You'd like to use a JSF UIData based component instead of c:forEach. A fullworthy JSF alternative to the c:forEach is Tomahawk's t:dataList. Use it and your problem will be solved.
If it happens that you're using Facelets instead of JSP, you can also use its ui:repeat instead.