I have followed the java play framework tutorial and created the todo task list that is the result of this tutorial:
http://www.playframework.org/documentation/2.0.4/JavaTodoList
I wanted to modify this project slightly so that instead of having label input the form I had two other inputs, starting location and end location.
Firstly I included the extra variables I required in the java class in Models/
#Id
public Long id;
#Required
public String starting_location;
#Required
public String end_location;
I also added this to the index.scala.html file:
#form(routes.Application.newJourney()) {
#inputText(journeyForm("Starting Location"))
#inputText(journeyForm("End Location"))
<input type="submit" value="Create">
}
I get the form fields "Starting Location" and "End Location" displaying as expected but when I click on submit the total number of journeys (or tasks for as described in the play example) does not increment and does not get added to the list of current journeys that can be deleted.
Any help is appreciated and I can post full source if required.
Thanks
The helper inputText is documented here.
You put there a label where the field name should be.
This should work:
#inputText(
journeyForm("starting_location"),
'_label -> "Starting Location"
)
Related
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.
I’m using tapestry 5.3.7, and I want to use Ajax chaining select form elements : If I choose one option in a select element, another select appear to choose another element based on your first choice. I try a sample in the tapestry doc, and adapted for my project. Despite the fact that my custom code is very close to the sample, I always have the following error :
Render queue error in SetupRender[SelectZoneDemo:version]: Component SelectZoneDemo:version must be enclosed by a Form component.
Working sample from the doc (Chaining of select components CarMaker) http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/corelib/components/Select.html)
Here is my code :
Template file (.tml)
<t:form>
<p>
<t:errors />
</p>
<p>
<t:select t:id="selectApplicatifs" t:model="selectApplicatifs"
t:value="selectedApplicatif" validate="required" zone= "VersionZone"
t:zone="versionZone" t:encoder="ApplicatifDtoEncoder" />
</p>
<t:zone t:id="versionZone" id="versionZone">
<t:if test="selectedApplicatif">
<p>
<t:select t:id="version" model="selectVersions" t:encoder="VersionDtoEncoder" />
</p>
</t:if>
<p>
<t:submit value="literal:Submit" />
</p>
</t:zone>
</t:form>
Java file
#Inject
private AjaxResponseRenderer ajaxResponseRenderer;
#Inject
private IServiceApplicatif serviceApplicatif;
#Inject
private SelectModelFactory selectModelFactory;
#Property
#Persist
private SelectModel selectApplicatifs;
#Property
#Persist
private String version;
#Property
#Persist
private SelectModel selectVersions;
#Inject
#Property
private ApplicatifDtoEncoder applicatifDtoEncoder;
#Inject
#Property
private VersionDtoEncoder versionDtoEncoder;
#Property
#Persist
private ApplicatifDto selectedApplicatif;
#InjectComponent
private Zone versionZone;
public void onActivate() {
List<ApplicatifDto> listApplicatifs = serviceApplicatif.findAllApplicatifDto();
List<VersionDto> listVersionApplicatifs = new ArrayList<VersionDto>();
selectApplicatifs = selectModelFactory.create(listApplicatifs, "nom");
if (selectVersions == null) {
selectVersions = selectModelFactory.create(listVersionApplicatifs,"version");
}
}
public void onValueChangedFromSelectApplicatifs(ApplicatifDto applicatifDto) {
List<VersionDto> versionList = applicatifDto.getVersionList();
selectVersions = selectModelFactory.create(versionList,"version");
ajaxResponseRenderer.addRender(versionZone);
}
Rendering zones within a form via ajax can get tricky as you have discovered. Fields require a FormSupport instance to be on the Environment stack. This is normally added to the environment as the parent form renders but as you have discovered, when rendering a zone within a form the FormSupport is not available.
Here's a few options:
Have a zone that wraps the entire form and update the whole form via ajax
Instead of refreshing a zone, use some javascript (via JavaScriptSupport) to update the options in an existing select menu
Use the Observe mixin to update zones in the form. Instead of using the core tapestry select component, you could render your own select. This might require you to use #RequestParameter to get the values serverside when the form is finally submitted.
Use the FormInjector. I've never used it myself but I think it somehow spoofs the environmental. I'm not sure how you'd pass the user's selection in the event. I think this component may have also been scrapped in tapestry 5.4.
I have a web application in Java that performs title matching.
The Servlet is the controller and in one of the methods of the Servlet, I am comparing two list of titles. The first list is in a HashMap and the second is from a query ResultSet.
What I want to do is to automatically match those with same title and give the user the option to confirm the ones with some similarities (business logic). Basically, I need to get user input and then return at the same point to continue.
I tried JOptionPane dialog box and it didn't work.
Now I am trying to forward to another HTML page to get user input and then return to the Servlet.
Below is the Servlet code:
while (Querylist.next()) {
String title = Querylist.getString(1).trim().toLowerCase();
if (MyMap.containsKey(title))
{
// confirm match
} else
{
//some title2 is like title
request.setAttribute("Title1", title);
request.setAttribute("Title2", title2);
RequestDispatcher view = request.getRequestDispatcher("TitleMatch.jsp");
view.forward(request, response);
ResultMatch= request.getParameter("ResultMatch");
if (ResultMatch.equals("YES"))
{
// confirm match
}
}
}
HTML Page:
<B> <%= request.getAttribute("Title1")%></B>
<B> <%= request.getAttribute("Title2")%></B>
<FORM method="get" action="DataMerge">
<input type = "radio" name="MatchResult" value="YES" /> YES
<input type = "radio" name="MatchResult" value="NO" checked/>NO
<button type = "submit" formaction="DataMerge" > <b>CONFIRM</b>
</FORM>
EDIT: the loop works and I'm having a java.lang.IllegalStateException Exception.
Does anyone can help to figure out how to do that efficiently in plain Java?
I searched all over SO and haven't found something similar. Thanks in advance.
You might want to reconsider your approach as there are number of fundamental problems with the code you have written. For example:
The while loop test it not correct. Assuming that you are using an Iterator then the test should be list.hasNext();
The if test is nested and incorrect. You cannot use the identifier Map as it is the name of the class, you should use the name of the map object.
If the loop worked the view.forward(request, response); would result in an java.lang.IllegalStateException exception, on the second cycle, as its not possible to resend a response.
I suggest that instead of trying to send each title pair one at a time, that you display them all (or some if there are too many) on one JSP with a yes button next to each pair and as the user clicks the yes button an AJAX call is made to another servlet that updates the database (or an array to latter be used to update the database).
There are some good tutorial about using AJAX and JSP here of SOF and in YouTube.
I am developing a registration web app using Struts2 and need some guidance.
Background:
On the registration form, there is a set of five form fields: 1 text box, and 4 drop down select boxes. The five fields describe a person's primary position in an educational setting: the text field allows the user to insert their job title, and the drop down menus allow the user to select what school, institution, department, and division they belong to. The drop down menus are initialized with options that are stored in a database (inside the registration action, array lists are initialized with these values before the form is displayed). For example:
<s:select emptyOption="true" key="school1.schoolId" list="schoolList" listKey="schoolId" listValue="schoolName" required="true" />
Problem:
I need to provide the user with the ability add an X number of secondary positions. On the registration form, a user can click an "add another affiliation" button, and a new set of the 5 form fields are displayed. These fields will also need to be validated, and saved when the user clicks the form's submit button.
What would be the best approach to tackling this problem?
So far, I have only declared array lists for each form field, like so:
private List<String> jobTitles = new ArrayList<String>();
private List<School> schools = new ArrayList<School>();
private List<Institution> institutions = new ArrayList<Institution>();
private List<Department> departments = new ArrayList<Department>();
private List<Division> divisions = new ArrayList<Division>();
But I do not know how to proceed. How do I display the initial 5 fields for the primary position? If I use Javascript to insert new form fields dynamically, how do I initialize the dynamic drop down menus with the options stored in the database? How do I retain these values if the page is reloaded?
Any help is appreciated - thanks!
The basic problem you need to tackle is how to get an indexed list of request parameters into your action class. This is quite simple, and I think you are on the right track by starting off by creating Lists of input parameters. I found a bit of documentation on the subject here. Basically you can have form fields with names like jobTitles[0], jobTitles[1] which would be used to populate the jobTitles List.
However, I think the concept of 'Affiliation' deserves a class of it's own:
class UserAffiliation {
private String title;
private String schoolId;
private String institutionId;
private String departmentId;
private String divisionId;
// Make sure that there is a no-args constructor (default or explicit) for Struts to create instances.
// Add getters and setters
}
In your action class:
private List<UserAffiliation> affiliations;
...
// getter and setter for affiliations
Would be enough to capture the user input.
Your jsp could look something like:
<form action=".." method="post">
<div class="affiliation">
<s:textfield name="affiliations[0].title"/>
<s:select name="affiliations[0].schoolId" list="schools" listKey="schoolId" listValue="schoolName"/>
...
</div>
<s:if test="affiliations != null && affiliations.size > 1">
<s:iterator value="affiliations" begin="1" status="status">
<s:textfield name="affiliations[%{#status.index + 1}].title"/>
<s:select name="affiliations[%{#status.index + 1}].schoolId" list="schools" listKey="schoolId" listValue="schoolName"/>
...
</s:iterator>
</s:if>
....
</form>
<div id="affilationTemplate" style="display:none;">
<div class="affiliation">
<s:textfield name="affiliations[__IDX__].title"/>
<s:select name="affiliations[__IDX__].schoolId" list="schools" listKey="schoolId" listValue="schoolName"/>
</div>
...
</div>
Note the div affilationTemplate. You could use JS to get the html of this template, replace __IDX__ with the appropriate index, and append to the form contents when the user clicks on the 'add another affiliation' button. This makes sure that the newly added select boxes are pre-populated with appropriate values.
The iterator block displays what ever the values the user had already submitted (with the exception of the 'primary affiliation', which is already displayed above it).
NOTE: You should of course, try to get rid of the repeated form elements if possible. I would try with extracting them into an include.
My command object have a list of objects. I want to bind a text field to the attribute of the object inside that list. Is it possible to do in Spring MVC?
Command object class
public class SubDevisonDto {
private String devId;
private List subDevisions;
Subdevision object class mentioned in the list
public class SubDivison implements Serializable{
private String subDivisonName;
private String createdBy;
private String createdDate;
private String developerID;
private List users;
I want text box to set the value for subDivisonName field.
I have written the Spring MVC tags like this.
<spring:bind path="subdivisondto.subDevisions[0].subDivisonName">
<span class="formw">
<input name="subDivisonName" type="text" style="width:350px;" />
</span>
</spring:bind>
Just for test purpose I have given it as 0. If it's working I can make it to a variable. my requirement is, I should let the user to dynamically add subdevision objects. So, initially when page is loading I will just show one text box. I will give a button for him to add if he want to add more. I will dynamically generate text boxes when he clicks the add button. After that I have to submit the form with the list.
This jsp code gives me an error. It says:
org.springframework.beans.NullValueInNestedPathException
Is there anyway for me to do this in jsp code?
I found the answer for my question. But, it's not the solution for my requirement as I need to implement a dynamic list. but I found a solution for this question.
As I understood, first time we have to send data from back end to bind input elements. I didn't find a way to bind form elements which takes input without sending a list data from beck end. But when we send data and bind the elements, we can take input from those elements. So, I think to bind the element in a situation like this we need to send data first time. Correct me if this statement is wrong. Because, that would be a more good solution for me.
We need to use the lazy list and jsp code is bit modified.
Your command class object should be created as below mentioned.
import org.apache.commons.collections.list.LazyList;
import org.apache.commons.collections.FactoryUtils;
public class SubDevisonDto {
private String devId;
private List subDevisions =
LazyList.decorate(
new ArrayList(),
FactoryUtils.instantiateFactory(SubDivison.class));
JSP code should look like below.
<c:forEach items="${subs.subDevisions}" var="obj" varStatus="gridRow">
Binding an input element text box
<spring:bind path="subdivisondto.subDevisions[${gridRow.index}].subDivisonName">
<span class="formw"><input name="<c:out value="${status.expression}"/>" type="text" style="width:350px;" />
binding an input element check box. This input element makes a list.
<spring:bind path="subs.subDevisions[${gridRow.index}].users">
<c:forEach items="${obj.users}" var="dependenttwo" varStatus="dependentRowtwo">
<li>
<input name="<c:out value="${status.expression}"/>" type="checkbox" class="users" value="<c:out value="${dependenttwo}"/>"/>
<c:out value="${dependenttwo}"/>
</li>
</c:forEach>
</spring:bind>
`subs` is a map key name. the value for this key `subs` is a list of my DTO objects which named as `SubDevisonDto `
This code works fine for me.
Thanks the support given.
In dto :
private List<SubDivision> SubDivisions = new AutoPopulatingList<SubDivision>(new SubDivisionFactory());
and factory would be something like:
public class SubDivisionFactory implements AutoPopulatingList.ElementFactory<SubDivision> {
public String createElement(int index) {
SubDivision subDivision = new SubDivision();
return subDivision;
}
}
using AutopopulatingList from spring. And your jsp will look the same, you can iterate over as many as you want.