I have a table with many rows, and each row has a link to a modal dialog box using struts2-jquery. I need to set a unique ID for each dialog in order to set this up, but I've tried multiple options without luck.
<s:iterator value="myBeanList" var="rrSum" status="status">
<tr>
<td>
<s:url id="ajax%{status.index}" action="smoRiskRegister" var="ajaxURL">
<s:param name="requestRiskID"><s:property value="#rrSum.rid" /></s:param>
</s:url>
<sj:dialog id="dialog3" href="%{ajaxURL}" title="Testing" />
<sj:a openDialog="dialog3"><s:property value="#rrSum.rid" /></sj:a>
</td>
</tr>
</s:iterator>
So instead of "dialog3" I want something like dialog%{status.index}. I can set the ID to this... but how do I reference it in the anchor tag? Unfortunately there is no var parameter for dialog :(
Just use %{#status.index} in anchor tag as well.
<sj:dialog id="dialog%{#status.index}" href="%{ajaxURL}" title="Testing" />
<sj:a openDialog="dialog%{#status.index}"><s:property value="#rrSum.rid" /></sj:a>
Note # sign, one have to use it when accessed object is not in the OGNL root.
The Action instance is always pushed onto the value stack. Because the Action is on the stack, and the stack is the OGNL root, references to Action properties can omit the # marker. But, to access other objects in the ActionContext, we must use the # notation so OGNL knows not to look in the root object, but for some other object in the ActionContext.
Read about OGNL in Struts2: http://struts.apache.org/2.x/docs/ognl.html.
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 display rows in an HTML table with a checkbox in a column in each row of the table something like the following.
<s:iterator value="objects" status="loopStatus">
<td>
<s:label for="%{id}" value="%{#loopStatus.index+1}"/>
<s:checkbox id="%{id}" name="chk" fieldValue="%{id}" value="false"/>
</td>
<!--Other columns-->
</s:iterator>
objects is is a list of objects of a JPA entity, List<Entity> initialized in an action class. id is a value of type Long that corresponds to a primary key column in the database.
The values of these checkboxes are set to its corresponding property in an action class, when the form is submitted.
private List<Long>chk;
//setters & getters.
The values of selected checkboxes are correctly set to this property chk. This list of values is then used to delete rows from the database.
This works just fine. A problem occurs, when there is only one row in the table. In which case, an unnecessary conversion error occurs, while performing operations other than deletion (like updating/inserting a row) which requires this checkbox to be selected which is quite unnecessary and should happen only while performing deletion.
Invalid field value for field "chk".
If I deliberately add an extra checkbox with the same name chk then, this conversion error disappears.
Presumably it appears that a single checkbox is not correctly mapped to a list of values of type Long, List<Long>.
What is the way to get rid of this error, when there is only a single row to be displayed in an HTML table?
If you don't check a single checkbox it value by default is set to false. You can set the default in checkbox interceptor uncheckedValue property.
Additionally you may consider to add hidden field so that checkbox interceptor will think there are multiple chekboxes when there is only one and won't add default value.
For your checkbox the hidden field name will be __checkbox_chk.
<s:hidden name="__checkbox_chk"/>
Try this one which explicitly cites the array index:
<s:iterator value="objects" status="loopStatus">
<td>
<s:label for="%{id}" value="%{#loopStatus.index+1}"/>
<s:checkbox id="%{id}" name="chk[%{#loopStatus.count}]" fieldValue="%{id}" value="false"/>
</td>
<!--Other columns-->
</s:iterator>
I am guessing I may be missing something simple here but I have done a lot of searching and have not found the answer...
Summary
How can I use the ready made libraries which support JavaBeans to help me take a checkbox from an HTML form and use it to populate a boolean field in a JavaBean which will then be used to update a database table? If this isn't going to work what approach would be best? Ultimately I am trying to avoid writing field specific code in what is, in all other respects, generic code.
Description
I have a jsp file (addScreen.jsp) which displays a form.
I want to use the data which is entered into the form to populate a JavaBean (type Screens).
I will then use the JavaBean (via Hibernate) to update a record in a database table.
The database table (Screens) contains a column, enabledFlag which has a boolean type.
The way I have represented this in the html form is as a checkbox.
In my controller code, when I process the form I want to use the elegant and generic functionality provided to support JavaBeans.
So I am trying to use the BeanUtils.populate() method to take data from the HTML form and use it to populate the screen field of type Screens.
This approach works very well for most of the fields in screen and converts the data from the form into the right type and stores it within the screen JavaBean.
But (and here is the problem) it doesn't process the checkbox and create a true or false value to go into the Boolean field within the Screens JavaBean. In fact it always leaves that field populated with false. I'm guessing it doesn't do anything and it defaults to false.
I think I can see why this doesn't work exactly as I have done it (but feel free to correct me). The way the checkbox state is recorded in the HttpServletRequest parameters probably isn't going to reflect what BeanUtils.populate() is expecting so it can't do anything useful. But I am not sure what it is expecting so I don't know how to manipulate the input so that populate() gives the right answer (not sure if that is very clear).
So given the above, my questions are:
Is there anything fundamentally wrong with what I am trying to do - i.e. use BeanUtils or other general purpose JavaBean library to populate a JavaBean from an HTML form which includes a checkbox? If so please let me know a better way of achieving my goal.
Assuming that there isn't a fundamental problem with what I am trying to do, am I using the wrong method or approach or should I be manipulating the data in some way before calling populate() so that it interprets the checkbox correctly?
Any other tips about how to go about this?
I have tried to include some relevant code below without swamping readers with irrelevant detail, but feel free to ask to see more if it would help. All feedback welcome.
Code Snippets
Form from addScreen.jsp which includes the enabledFlag checkbox
<form id="editScreen" method="post" action='Controller.do'>
<table>
<col class='label' />
<tr>
<td>
<label>Screen Name:</label>
</td>
<td>
<input type='text' name='name'>
</td>
</tr>
<tr>
<td>
<label>Enabled?:</label>
</td>
<td>
<input type="checkbox" name="enabledFlag" value="Enabled" checked>
</td>
</tr>
<tr><td>
<input type='submit' name='addButton' value='Add'>
</td></tr>
</table>
</form>
Declaration of enabled flag within Screens JavaBean
private boolean enabledFlag;
#Column(name = "EnabledFlag", nullable = true, insertable = true, updatable = true, length = 0, precision = 0)
#Basic
public boolean isEnabledFlag() {
return enabledFlag;
}
public void setEnabledFlag(boolean enabledFlag) {
this.enabledFlag = enabledFlag;
}
Call to BeanUtils.populate()
BeanUtils.populate(data, request.getParameterMap());
data is of type Screens and request is the HttpServletRequest containing the form data.
Just a guess - the value of your flag is "Enabled", try something like "true", "on" or "1".
Or do you have mapping code that maps "Enabled" to true?
Also, there seems to be a problem when the checkbox is unchecked, as in that case, nothing is sent to the server - there seems to be a common solution in using Javascript to set a hidden field to a value "on" or "off" and considering the hidden field only, and ignoring the checkbox itself.
See here for further reference: http://books.google.de/books?id=KNjkjBDEKssC&lpg=PT107&ots=9wZRkd_Y48&pg=PT107#v=onepage&q&f=false
I'm new to the front end side of Java EE and HTML5. I have read that you could use the data attribute to read through the DOM. How would you properly use this to get a session attribute already set by java. Compared to the other methods such as using a hidden input.
<input id="sid" type="hidden" name="series" value="${sessionScope.series} />
var sid = document.getElementById("sid"), series;
Use something like this:
<div id="div1" data-special-value="${sessionScope.series}"></div>
And get the attribute value like:
document.getElementById("div1").getAttribute("data-special-value")
Or even ( http://caniuse.com/dataset ):
document.getElementById("div1").dataset("special-value")
Or with jQuery:
$("#div1").attr("data-special-value")
// or
$("#div1").data("special-value")
Although I'm not sure storing a session value on an element is right. It's definitely not wrong, I'm just wondering what you'd need/use it for with sessions. Sessions appear once.
The data-* attributes are more useful with storing related data to something. For example, if you loop through a bunch of database records and print their columns, but want to also store the row's database id once, you'd use:
<c:forEach items="${rows}" var="row">
<tr data-row-id="${row.id}">
<td>${row.name}</td>
<td>${row.description}</td>
</tr>
</c:forEach>
Then if you want to get the original row.id value, it's stored in one place an encompasses everything it pertains to (the columns). This is usually how/where I use data-* attributes. Of course, there are many ideas/uses for this.
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.