I am working on a Struts2 application. I am setting the value of a hidden field in JSP with the purpose to access it by JavaScript.
My JSP code:
<s:iterator value="collegelist">
<tr>
<td align="center"><s:property value="collegename"/></td>
<s:hidden name="hiddenname" key="collegename" />
</tr>
</s:iterator>
My JS code:
var myForm = document.frmAction;
var text = myForm.hiddenname.value;
alert("hidden field text is:" + text);
The alerts shows a blank value.
What is the cause and how can I solve this?
Try
element = document.getElementsByName("hiddenname");
alert(element[0].value);
You generate multiple fields having the same name, since your code is inside a s:iterator tag. You should obviously have such a loop in your Javascript as well :
var hiddenFields = document.getElementsByName("hiddenname");
for (var i = 0; i < hiddenFields.length; i++) {
alert("hidden field text is::" + hiddenFields[i].value);
}
Also, verify the the value is not blank in the generated HTML, and that the hidden fields'a name is hiddenname.
I tried your code and it surely works.. problem is somewhere in your server code itself..
Look here: http://jsbin.com/ajajo4/2/edit
Make sure you have only one form with the name "frmAction" and only one hidden field with the name "hiddenname". If you have multiple, you'll get an array instead of a single value.
The root of the problem is that you are inside of an iterator. Struts updates the name for you in order to correctly hook everything up. If you pull up your page and view source, your hidden field will probably look something like this:
<input type="hidden" name="collegelist[0].hiddenname" value="thename"/>
Regardless, if you want the retrieval by name to work, do not trust the name that you supply to a struts tag. Always pull up the generated source and look at what name the field actually has.
Related
On my website I have a few checkboxes each of them contains id in value attribute. After submitting form I'd like to have a list containing ids of checked checkboxes to be passed to the controller. That's how I want to make new page comparing n products.
Controller can accept List<Long> or long[]. That's what I have for now:
HTML:
<form th:action="#{/comparison}" th:object="${productsComparison}" target="_blank" method="post">
<table>
<tr data-th-each="item, iter : ${items.item}">
<td>
<input type="checkbox" th:name="|productsComparison.ids[${iter.index}]|" th:value="${item.id}"/>
</td>
</tr>
</table>
I've added to my controller List<Long> wrapped in ProductComparison with appropriate getters and setters. After submitting form list is always null.
Controller:
#RequestMapping("/productsPage")
public String showProducts(Model model) {
ProductsComparison productsComparison = new ProductsComparison();
model.addAttribute("productsComparison", productsComparison);
}
#RequestMapping("/comparison")
public String compareProducts(#ModelAttribute ProductsComparison productsComparison) {
System.out.println("List: " + productComparison.getIds());
// Always shows null
return "comparison";
}
public class ProductsComparison {
private List<Long> ids;
// Getters & setters
}
The underscores __ are ThymeLeaf's syntax for a preprocessing expression. Or in layman's terms, the stuff inside of the underscores are processed before the rest of the expression.
This is important because your expression is using an array, and the ${iter.index} portion of it gives the array index.
If you are curious or if anyone else stumbles upon this. th:name is no different than the html attribute name. The ThymeLeaf engine will just shove a name attribute into the html entity or overwrite the old one. ThymeLeaf has a ton of properties like this. th:field is a totally different beast though. It is what tells ThymeLeaf to bind the input of your form to the back forming bean or your model attribute, th:object="${productsComparison}". So with the expression th:field="*{ids[__${iter.index}__]}", Thymeleaf is going to call productsComparison.getIds[0] and the corresponding setter.
Note about th:name if you are submitting with Javascript of any kind, you probably want to use this. Most likely you are serializing your form, and the JSON created by this method call will use the name property.
If you want to know more about ThymeLeaf preprocessing expressions, there is a bit in the documentation about it.
I've finally found solution. Instead of th:name I had to use th:field.
th:field="*{ids[__${iter.index}__]}"
Because it's field I didn't have to specify object productsComparison before ids. ids field is List<String>.
To be honest I have no idea what underscores do, I will be glad if someone could explain.
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 have custom tag which contains form with text input and submit. I want to validate this text input using JS, so my custom tag output should look like:
<script type="text/javascript">
function validate(form) {
var text = form.textInput;
// validation code
}
</script>
<form onsubmit='return validate(this);'>
<input type='text' name='textInput'/>
<input type='submit'/>
</form>
(Note, this code simplified!)
My problem appears when I want to use this tag twice or more times at page - I want to print form at page again, but not JS validation code! Validation code must be unique at the page. How can I archive that? My custom tag extends javax.servlet.jsp.tagext.TagSupport
I found the most suitable solution for me.
Class javax.servlet.jsp.tagext.TagSupport contains protected field pageContext which presents... page context! I can easily access context attributes of javax.servlet.jsp.PageContext. So, I put next code in my custom tag:
public int doStartTag() throws JspException {
if (pageContext.getAttribute("validated") == null) {
// validation code writing
pageContext.setAttribute("validated", true);
}
...
}
If condition would be reachable only once per page rendering.
Hope it would be useful for someone.
I suggest you to try to embed that JavaScript function in some .js file an import that file. If you don't want to do that, for some reason you should try to define that function dynamically, if it is not defined:
if (typeof window.validateMyForm === 'undefined') {
window.validateMyForm = function(form) {
var text = form.textInput;
// validation code
}
}
As you guess this should define function only if it is not already defined.
First answer is correct, but that means that programer must know where in code are already inserted custom tags and according to that this whether to set that parameter to true or false. And what about code changes, you will have to always go thought whole page and revise all used tags on a page.
Make the custom tag to accept a parameter that toggles the validation on or off, and of course have it generate different code depending on the value of the parameter.
[Warning] I'm new to JSP/Struts/JSTL. This is probably a newbie question :)
I have a form that contains a collection:
public class ServiceForm extends AbstractForm
{
private List<SrvDO> allSrv = new ArrayList<SrvDO> ();
}
I can see the object data correctly in my form using the JSP. The page displays 5 input box with the data from the database correctly:
<c:forEach items="${serviceForm.allSrv}" var="srv">
<html:text name="srv" property="nbDays"/>
</c:forEach>
<html:submit/>
But when I press the submit button, the form does not contains the updated data for "nbDays". I still see the same data as it was shown before the update. What am I missing that says to struts: for each srv, update the "nbDays" data?
Found the answer on the spring forum:
Your form:input tag doesn't and
shouldn't know anything about the fact
that it is used inside another tag.
That is why you need to include the
index.
So the solution is:
<html:text property="allSrv[${srvSta.index}].nbDays"/>