thymeleaf object binding can ignore case for form fields? - java

Newly started using thymeleaf for my application. I am building a dynamic form from controller where form fields are created as a list of map. Each key value pair is iterated as below.
<form th:action="#" th:object="${foo}" method="post">...
<input type="text" id=${element.key}
th:name=${element.key} th:value="${element.value}"/> ...</form>
My Pojo has properties in lower case as following java standard. But when building the key property my code uses the Capital letters from external file and also in order to have a better readability on UI not converting from upper case to lower case conversion in
mydata.put("KEY", 90);.
Upon submitting the page, my form elements not binding with propery key of Foo class due to KEY to key is not mapping. Getting null for the form fields due to input form field name as 'KEY'. I suspect the reason for getting null values for input text fields entered in html pages are due to case-sensitive of object properties in Foo class.
class Foo { private String key; //KEY can be a fix but naming convention is missing. }
Is there any thymeleaf tags available to ignore cases when binding html-elements to objects ? Or shall I use any JavaScript tweak upon submitting the form ? Like sending lower case and converting to upper case on form load to display ?

you can try to use ${#strings.toLowerCase(element.key)}
<form th:action="#" th:object="${foo}" method="post">...
<input type="text" th:id="${#strings.toLowerCase(element.key)}" th:name=${#strings.toLowerCase(element.key)} th:value="${element.value}"/> ...
</form>

Related

Bind list or array to form in Thymleaf

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.

How to store several inputs to an Array in Spring Framework

I'm new to Spring MVC and I'm creating a form with several attributes that the user needs to complete and I want to store a list of numbers into an Array and not create a variable for each field
I try this code, but doesn't work :
Linea 1 <form:input type="number" path="numberArray[0]"/>
Linea 2 <form:input type="number" path="numberArray[1]"/>
...
In Spring 3+, <form:input/> cannot be used for this because the W3C HTML Specification changed to disallow [] in form input name attributes. Here is a good writeup of using the raw HTML input elements to support rows/arrays of fields (it's essentially what you were trying to do with numberArray[index] but using the raw HTML input element).

Striving to understand Spring MVC model and specific controller method

I have encountered the following code in a Spring-based Java application.
This is the controller:
#RequestMapping(value="/plants/form")
public String form(Model model){
model.addAttribute("plant", new Plant());
return "plants/create";
}
I have several questions regarding this snippet.
I know that form method is called for requests to /plants/form,
but I would like to know which method invokes form and passes arguments to it?
To me, it seems that a model is like a database. So, it looks like
model.addAttribute("plant", new Plant()); creates a Plant
instance and makes it accessible in a model under the name plant.
Thus, an attribute of a model seems to be
something like a field in DB. What is the exact meaning of
an attribute of a model?
What is value in #RequestMapping(value="/plants/form") and what
is the difference between aforementioned notation and
#RequestMapping("/plants/form")?
Consider this incomplete snippet of HTML:
<form class="form-horizontal" role="form" th:object="${plant}" th:method="post" th:action="#{/plants}">
<div class="form-group">
<label for="name" class="col-sm-2 control-label">Name</label>
<input type="text" th:field="*{name}"></input>
</div>
</form>
What is the meaning of $, *, # in "${plant}","*{name}" and
"#{/plants}". It is not clear to me.
1) If I understand your question correctly, then Spring MVC DispatcherServlet is responsible for routing request to your handler method based on configured HandlerMapping/HandlerAdapter.
2) Model is M in MVC, it has nothing in common with relational database. Rather consider it as a Map of String keys to Object values. Spring MVC model attributes are stored in request scope under the hood.
3) There is no difference, value is the attribute of #RequestMapping annotation. When you want to pass a single value argument and no other arguments, then it is possible to omit value by convention.
4) These are tags and attributes of Thymeleaf Standard and SpringStandard dialects. More information here.

javascript document.forms[0] and document.<formname> have different elements

I am trying to implement client side validation in Struts 2. my theme is xhtml. The javascript generated is not able to validate my code. After debugging , I found that Struts is using the following notation to refer the elements.
form = document.getElementById(<form id>);
service = form.elements['service'];
the point is that service is coming as undefined.
when I checked that form.elements is null; However if I access form using document.formname i am able to see the fields in elements collection.
I am thinking document.forms[0] is returning the same object as document.getElementById(formid). What is the difference?
The form element can access fields by name, for this purpose you should get the form element. You can do it in many ways, use document.getElementById() or document.forms[], or $("#formid"). Whatever way you choose doesn't matter. Just note that a document can contain many forms, so you should reference a correct one. Getting form element by id returns an element that has an id attribute, getting it by the index in the forms property you should know the correct index. Once you get the form element you can reference input fields by name. For example
<form id="formid">
<input name="service">
</form>
<script>
var v = document.getElementById("formid")['service'];
</script>

Struts 2 Select Tag Default Value

I'm creating a database record edit form using Struts.
<s:select id="status" name="newRecord.status" list="statusTypes" listKey="id" listValue="description" label="Status:" value="" /><br />
Example list:
Status' list:
1 Open
2 Closed
3 Pending
I want to set a default value on the status field as the current status which is stored in record.status which contains the string representation e.g. "Open".
If I set value="%{record.status} it doesn't work because that's not any list key. Is there a way I can set this value when I only have the string representation to work with?
Or should I redesign record.status to be an object with ID and String?
You should initialize the value of the newRecord.status that should be a separate property that contains the list key value. Then simply set the default value="%{record.status}". When I said the property I mean the bean property that is accessible via OGNL.
You need to use a hash instead of a list. Notice
listKey="id" listValue="description"
Then you can set the value = the key

Categories

Resources