Select model is lost when rendering a zone - java

I have an issue while updating the render on a select field with Tapestry.
I want to disable 2 fields (1 textfield and 1 select field) depending of what I selected in another field (also a select field). I want to render the disabled fields immediately so I am using the Tapestry Zone system to do so.
However I keep getting the following exception for the select field when I select an item from the "fruitOrVegetableSelect" list :
Parameter 'model' of component fruit/Edit:fruitNames is bound to null. This parameter is not allowed to be null.
Here is my code in the tml page :
<t:zone t:id="fruitsForEveryOneZone" update="show">
<tr>
<td> <t:select
t:id="fruitName" t:model="fruitNames"
value="fruit?.fruitName"
disabled="getDisabledFruitField()" />
</td>
<td><t:textfield t:id="numberOfFruits"
value="fruit?.quantity"
disabled="getDisabledFruitField()" />
</td>
</tr>
</t:zone>
And here is the code in the controller :
#OnEvent(component = "fruitOrVegetableSelect", value = EventConstants.VALUE_CHANGED)
public Object updateFruitOrVegetable(Plant plant)
{
if (plant.getName().equals("Fruit"){
this.disabledFruitField=false;
else {
this.disabledFruitField=true;
}
return new MultiZoneUpdate("fruitsForEveryOneZone", fruitsForEveryOneZone.getBody());
}
If I limit the zone so it only takes the textfield input it works fine (except that my select is never disabled). For some reason the "model" from my select field is lost in the process. Any idea why this happens and how I can avoid this problem?

This code is not showing how "fruitNames" is declared in java class. I guess that "fruitNames" is a variable and it's just lost. You should annotate "fruitNames" with #Persist and this should do the trick or declare "fruitNames" as a method (getFruitNames()).

Related

Best way to edit an object with Thymeleaf and Spring MVC

I'm working on a website in which users can add and edit things (it's not relevant describing what these things are in particular).
I'm implementing it using Thymeleaf for the frontend, Spring MVC for the backend and JPA for the database logic. Now I'm trying to implement the edit logic but I don't know which is the best way to do it.
What I'm thinking is: display to the user all the input fields (on a HTML page) that he is allowed to edit, already filled in with the current values. He can edit then whatever fields he wants and finally press the edit button to persist the changes.
Once I get the new object in the backend, I retrieve the old version from the database in order to check which field the user changed. For every field that got changed I update the old version and only when I've finished I call the JPA method save and I persist the new version of that object.
Is there a better way to do it?
It would be perfect if the object I put inside the model in order to display all its field to the user inside the HTML page, could mantain all the information of the old object and not just the ones the user can change. Let me explain better what I'm trying to say with an example:
Let's say the object we are trying to edit its called Person and has these attributes:
id
name
surname
money
nickname
sex
But the user can edit only the following attributes:
money
nickname
sex
so the controller which handler the get request of the page would look like this:
#GetMapping("person/{personId}/edit")
public String getEditPersonPage(#PathVariable Integer personId, Model model) {
Person person = personService.getById(personId); //person has all the attributes filled in
model.addAttribute("person", person);
and the controller which handler the put request looks like this:
#PutMapping("person/{personId}/edit")
public String editPerson(#ModelAttribute Person person, #PathVariable Integer personId){
personService.editPerson(person); //person has only the three fields filled in and all the other attributes as NULL
return "redirect:/person/" + personId;
}
the HTML page:
<form th:object="${person}" th:method="PUT">
<fieldset>
<p th:text="*{id}"></p>
<p th:text="*{name}"></p>
<p th:text="*{surname}"></p>
<input type="number" th:field="*{money}" th:value="*{money}" />
<input type="text" th:field="*{nickname}" th:value="*{nickname}" />
<input type="text" th:field="*{sex}" th:value="*{sex}" />
<input type="submit" value="Edit" />
</fieldset>
</form>
When I insert the object person inside the model to render the HTML page the object has all the attributes. Indeed I can decide which of its attributes display inside the HTML page (in this case only three: money, nickname and sex). But when the user press the submit button (edit), I receive only the fields displayed inside the HTML page (money, nickname, sex). So what I have to do is: I have to take these three fields, check if they are changed and if so, update the old version.
It would be perfect if when the user press the submit button, all the fields of person (and not just those three he is allowed to update) could be retrieved by the controller. In that case I could skip the check phase and persist directly the new version inside the database (with the old values unchanged and not set to NULL).
Any thoughts?
You can use readonly attributes for the ones that are not going to be edited.
I think is the best way in order to keep all the values visible in the form to give all the info to the user that is editing. All the values will be submitted and serialized with your object, but the form just allows to edit the three of them that you need.
A readonly element is just not editable, but gets sent when the according form submits. A disabled element isn't editable and isn't sent on submit.

Deleting multiple rows using checkboxes in Struts2

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>

How do I use BeanUtils.populate to populate a bean from a form which has a checkbox

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

How to update a the contents of a list displayed on JSP using Struts2?

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.

getting hidden fields value

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.

Categories

Resources