Apache Wicket - Combining tutorials - html

actually i have to learn wicket for a practical course and I have some problems. i tried to combine two of the wicket examples from the wicket library, but it failed and i dont know why.
The error message says:
Last cause: Unable to find component with id 'form' in [BorderBodyContainer [Component id = navomaticBorder_body]]
Expected: 'navomaticBorder:navomaticBorder_body:form'.
Found with similar names: 'form'
There are two examples i want to combine: the navomatic side-bar to have some links between my sites and a simple password validator.
NavomaticBorder.java
public NavomaticBorder(final String id) {
super(id);
addToBorder(new BoxBorder("navigationBorder"));
addToBorder(new BoxBorder("bodyBorder"));
}
NavomaticBorder.html
<html>
<head>
<title>Wicket Examples - navomatic</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<wicket:border>
<p>
<table height = "100%">
<tr>
<td height = "100%" valign = "top">
<div wicket:id = "navigationBorder">
<b>Navigation Links</b>
<p>
<wicket:link>
Seite1<br/>
Seite2<br/>
Seite3
</wicket:link>
</p>
</div>
</td>
<td valign = "top">
<span wicket:id = "bodyBorder">
<wicket:body/>
</span>
</td>
</tr>
</table>
</p>
</wicket:border>
</body>
</html>
Page1.html
<html>
<head>
<title>Wicket Examples - navomatic</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<span wicket:id = "navomaticBorder">
<h1>Registration 1</h1>
<form wicket:id="form">
<p><label>Username</label>:<input wicket:id="username"
type="text" size="20"></p>
<p><label>Password</label>:<input wicket:id="password1"
type="password" size="20"></p>
<p><label>Confirm Password</label>:<input wicket:id="password2"
type="password" size="20"></p>
<input type="submit" value="Register">
</form>
<div wicket:id="feedback"></div>
</span>
</body>
</html>
Page1.java
public class Page1 extends WebPage {
/**
*
*/
private static final long serialVersionUID = 8070623982828503750L;
public Page1() {
add(new NavomaticBorder("navomaticBorder"));
add(new FeedbackPanel("feedback"));
final TextField<?> username = new TextField<String>("username",
Model.of(""));
username.setRequired(true);
FormComponent<String> password1 = new PasswordTextField("password1",
Model.of(""));
password1.setLabel(Model.of("Password"));
password1.add(StringValidator.minimumLength(8));
password1.add(new PasswordPolicyValidator());
FormComponent<String> password2 = new PasswordTextField("password2",
Model.of(""));
Form<?> form = new Form<Void>("form") {
private static final long serialVersionUID = -8653853765358238769L;
#Override
protected void onSubmit() {
info("Form submitted");
}
};
form.add(new EqualPasswordInputValidator(password1, password2));
add(form);
form.add(username);
form.add(password1);
form.add(password2);
}
}
I think thats the code parts who may cause the error, when i let all of them working alone theres no problem, just when i combine this in the last html file, its throwing an error.
I have no real experience with Html, maybe thats the cause but i hope its enough data to help me :)
Richie

It's looking for your form in the element navomaticBorder. So you should add the form to the navomaticBorder.
Try changing your code to this:
public class Page1 extends WebPage {
/**
*
*/
private static final long serialVersionUID = 8070623982828503750L;
public Page1() {
NavomaticBorder nav = new NavomaticBorder("navomaticBorder");
add(nav);
add(new FeedbackPanel("feedback"));
final TextField<?> username = new TextField<String>("username",
Model.of(""));
username.setRequired(true);
FormComponent<String> password1 = new PasswordTextField("password1",
Model.of(""));
password1.setLabel(Model.of("Password"));
password1.add(StringValidator.minimumLength(8));
password1.add(new PasswordPolicyValidator());
FormComponent<String> password2 = new PasswordTextField("password2",
Model.of(""));
Form<?> form = new Form<Void>("form") {
private static final long serialVersionUID = -8653853765358238769L;
#Override
protected void onSubmit() {
info("Form submitted");
}
};
form.add(new EqualPasswordInputValidator(password1, password2));
nav.add(form);
form.add(username);
form.add(password1);
form.add(password2);
}
}

Related

How to initialize an external reference in Thymeleaf?

If I had a Java class called for instance Buffet and one of its fields was something like:
#ManyToOne
private Chef chef
and I had to create a new Buffet object in an html form using Thymeleaf, how would I be able to refer to this chef field? At the moment my html looks like this:
<form th:action="#{/newBuffet}" method="POST" th:object="${buffet}">
<div>
<div>
<span><input type="text" th:field="*{name}" placeholder="name"/></span>
</div>
<div>
<span><input type="text" th:field="*{chef}" placeholder="chef"/></span>
</div>
<div>
<span><button type="submit">Invio<i class="material-icons">done</i></button></span>
</div>
</div>
</form>
and my controller like this:
#RequestMapping(value = "/newBuffet", method = RequestMethod.GET)
public String formBuffet (Model model) {
model.addAttribute("buffet", new Buffet());
return "newBuffet.html";
}
#RequestMapping(value = "/newBuffet", method = RequestMethod.POST)
public String addBuffet (#ModelAttribute("buffet") Buffet b, Model model) {
this.buffetService.save(b);
model.addAttribute("buffets", this.buffetService.listBuffets());
return "buffets.html";
}
the error it gives is, of course, because of the way Thymeleaf's input takes only strings whilst my input is an instance of my class Chef.

HTML Select option does not work after validation error in Thymeleaf SpringBoot

I have a form where a user can submit his team to the web application. He can select an option and enter his name. I have validated the name field that it cannot be blank. If the user leaves the name field blank and clicks "add", the page refreshes with the error name "enter name", but the selected option cannot be opened. User can not select option again and change it. It is not possible to move on.
Using java-Spring boot - Hibernate - thymeleaf
SubmitController
#GetMapping("/submit")
public String showForm (Model model) {
Submit submit = new Submit();
model.addAttribute("submit", submit);
List<String> rank = Arrays.asList("I", "II", "III", "IV", "V", "VI", "X" );
model.addAttribute("rank", rank);
return "submit_form";
}
#PostMapping("/submit")
public String submitForm (#Valid #ModelAttribute("submit") Submit submit, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "submit_form";
} else {
submitRepo.save(submit);
return "submit_ok";
}
}
Submit
#Entity
public class Submit {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotBlank(message = "Please enter your team name")
private String name;
private String rank;
//...
submit_form.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Submit your team</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css"
integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" th:href="#{/css/index.css}"/>
</head>
<body>
<nav th:replace="index :: nav"></nav>
<div class="container my-5">
<div align="center"><h1>Submit your team here! </h1></div>
<div class="card">
<div class="card-body">
<div class="col-md-10">
<form action="#" th:action="#{/submit}" th:object="${submit}" method="post">
<div class="row">
<div class="form-group col-md-8">
<label for="name" class="col-form-label">Name of your team: </label>
<input type="text" th:field="*{name}" class="form-control" id="name">
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}" style="color: red">Name error</span>
</div>
<div class="form-group col-md-8">
<label for="rank" class="col-form-label">Select Team's rank: </label>
<select th:field="*{rank}" class="form-control" id="rank">
<option th:each="p : ${rank}" th:value="${p}" th:text="${p}"></option>
</select>
</div>
<div class="col-md-6">
<input type="submit" class="btn btn-primary" value="Add team">
</div>
<div class="form-group col-md-8"></div>
</div>
</form>
</div>
</div>
</div>
</div>
The problem is that rank is no longer in the model when you show the errors.
The solution is to add it again to the model:
#PostMapping("/submit")
public String submitForm (#Valid #ModelAttribute("submit") Submit submit, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
List<String> rank = Arrays.asList("I", "II", "III", "IV", "V", "VI", "X" );
model.addAttribute("rank", rank);
return "submit_form";
} else {
submitRepo.save(submit);
return "submit_ok";
}
}
Side note:
It is best to use a GET-POST-REDIRECT flow with Thymeleaf. You are already doing the GET-POST part, but when the flow in the controller is ok, it is best to use a redirect:
#PostMapping("/submit")
public String submitForm (#Valid #ModelAttribute("submit") Submit submit, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
List<String> rank = Arrays.asList("I", "II", "III", "IV", "V", "VI", "X" );
model.addAttribute("rank", rank);
return "submit_form";
} else {
submitRepo.save(submit);
return "redirect:/submit";
}
}

Unable to use html controls from code behind

I am using html tags and I have written some code on code behind but it is not picking the values given to id. Infact it says the 'FileUpload1' does not exist in the current context. I do not want to use asp controls at all. I have heard adding runat = "server" does the thing but still cannot find the id's. What am I doing wrong?
<div id="mainContent">
<div class="column" id="colFull">
<div class="contentSection">
<div id="progress" style="display: none">
<img alt="Loading .." src="../../../Images/ajax.gif" />
</div>
<table width="100%">
<tr>
<td class="label" style="width:15%">
Upload File
</td>
<td class="description" >
<input type="file" id="FileUpload1" runat="server"
class="largeTextField" onclick="Upload" multiple="multiple"
style="width:260px;"/>
<input type="button" id="btnUpload"
runat="server" value="Upload" />
</td>
</tr>
</table>
mycodebehind:
public partial class PgPracFileUploader : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Upload(object sender, EventArgs e)
{
string filename = Path.GetFileName(FileUpload1.PostedFile.FileName);
string contentType = FileUpload1.PostedFile.ContentType;
using (Stream fs = FileUpload1.PostedFile.InputStream)
{
using (BinaryReader br = new BinaryReader(fs))
{
byte[] bytes = br.ReadBytes((Int32)fs.Length);
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
string query = "insert into tblFiles values (#Name, #ContentType, #Data)";
using (SqlCommand cmd = new SqlCommand(query))
{
cmd.Connection = con;
cmd.Parameters.AddWithValue("#Name", filename);
cmd.Parameters.AddWithValue("#ContentType", contentType);
cmd.Parameters.AddWithValue("#Data", bytes);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
}
Response.Redirect(Request.Url.AbsoluteUri);
}
}
It says FileUpload1 does not exist in the current context.
Try to change:
<input type="file" id="FieUpload1" runat="server" class="largeTextField" onclick="Upload" multiple="multiple" style="width:260px;"/>
to
Id Must be same as you are using in the .cs page
\/\/\/\/
<input type="file" ID="FileUpload1" runat="server" class="largeTextField" onclick="Upload" multiple="multiple" style="width:260px;"/>
As stated here your id attribute is case sensitive so you are using id then the server will just serve it up as it is in your page, but if you used ID then the server will be serve that control as a asp.net control.

Passing an array of ints from my HTML to Controller with Thymeleaf and SpringBoot

I am trying to pass an array of ints from my HTML back to my controller.
My flow is as follows:
I am retrieving data from an API and converting it to an Entity. All works fine.
However, I pass this to my HTML (Thymeleaf) and display some of the values to the User.
They then select one of the options and this is passed back to my Controller.
It is at this stage I lose the data I need.
In my Entity, I get the following data which I pass to the View (Example Below):
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "MOVIE_ID")
private long movieId;
#JsonProperty("title")
#Column(name = "TITLE")
private String title;
#JsonProperty("overview")
#Column(name = "OVERVIEW", length = 2000)
private String overview;
#JsonProperty("popularity")
#Column(name = "POPULARITY")
private float popularity;
#JsonProperty("release_date")
#Column(name = "RELEASE_DATE")
private String releaseDate;
#JsonProperty("genre_ids")
private int[] genreIds;
Then in my view, I display some values and hide the ids I dont need to display so that I can pass them back to my controller:
<form action = "#" th:action="#{/saveMovie}" method="post" th:object="${movie}">
<tr>
<td th:text="${movie.title}"></td>
<td th:text="${movie.releaseDate}"></td>
<td th:text="${movie.overview}"></td>
<input type="hidden" id="title" name="title" th:value="*{title}"/>
<input type="hidden" id="overview" name="overview" th:value="*{overview}"/>
<input type="hidden" id="popularity" name="popularity" th:value="*{popularity}"/>
<input type="hidden" id="releaseDate" name="releaseDate" th:value="*{releaseDate}"/>
<input type="hidden" id="genreIds" name="genreIds" th:value="*{genreIds}"/>
<td>
<div class="col-auto">
<button class="btn btn-primary" type="submit">Add</button>
</div>
</td>
</tr>
</form>
Controller to handle the call:
#PostMapping("/saveMovie") public String saveMovie(#ModelAttribute(value = "movie") Movie movie)
UPDATE***
Adding the GET/POST controllers that currently interact with this page:
#GetMapping("/searchMovie")
public String searchMovie(final Model model){
List<Movie> returnedMovies = new ArrayList<>();
model.addAttribute("movies", returnedMovies);
return "Search";
}
#PostMapping("/searchMovie")
public String searchMovieInTMDB(#RequestParam(value = "movieName", required = true) String movieName,
Model model){
List<Movie> returnedMovies = service.searchMovies(movieName);
model.addAttribute("movies", returnedMovies);
return "Search";
}
#PostMapping("/saveMovie")
public String saveMovie(#ModelAttribute(value = "movie") Movie movie){
service.storeMovie(movie);
return "WORK_IN_PROGRESS";
}
However, when I pass the values back to the controller I get the conversion error:
[Failed to convert property value of type 'java.lang.String' to required type 'int[]' for property 'genreIds']
I have changed it to String[] to test this works and error goes away but then I am presented with another problem in that it is converted to :
String Value Image
The only way I have found to pass the object back is by using the input tag and hiding them.
It converts the float fine, but can't handle the array of ints.
Is there a better way to pass objects back and forth between the controller using Thymeleaf or is there another attribute I can use to pass the array back and forth?
Thanks in advance
Conor
<form action="#" th:action="#{/saveMovie}" method="post"
th:object="${movie}">
<tr>
<td th:text="${movie.title}"></td>
<td th:text="${movie.releaseDate}"></td>
<td th:text="${movie.overview}"></td>
<input type="hidden" id="title" name="title" th:value="*{title}" />
<input type="hidden" id="overview" name="overview"
th:value="*{overview}" />
<input type="hidden" id="popularity" name="popularity"
th:value="*{popularity}" />
<input type="hidden" id="releaseDate" name="releaseDate"
th:value="*{releaseDate}" />
<input type="hidden" name="genreIds" th:field="*{genreIds}" />
<td>
<div class="col-auto">
<button class="btn btn-primary" type="submit">Add</button>
</div>
</td>
</tr>
</form>
#PostMapping("/saveMovie")
public String saveMovie(#ModelAttribute Movie movie) {
System.err.println(movie);
return "redirect:/movies";
}
#GetMapping("/movies")
public String getBooks(Model model) {
Movie movie = new Movie();
movie.setGenreIds(new int[] {4,5,6,7,8});
model.addAttribute("movie", movie);
return "movie";
}
Maybe You should send numbers as List to the controller.
#PostMapping("/saveMovie")
public String saveMovie(#RequestBody List<Movie> movies){
movieService.function_name(movies);
return "movies";
}
Another way to do this is using AJAX call to the controller. Just need to collect numbers as list in javascript and through ajax you should send array as json to controller. In controller you will parse them

Why does the <c:if> statement doesn't execute in the jsp? [duplicate]

This question already has answers here:
Can not find the tag library descriptor for “http://java.sun.com/jsp/jstl/core” [duplicate]
(18 answers)
Closed 7 years ago.
This is a Spring Web MVC project where I do input validation in server side. If there are any errors, then I add it to the model before sending it to the view.
Controller
#Controller("resultController")
public class ResultController {
private final ResultService resultService;
#Autowired
public ResultController(ResultService resultService) {
this.resultService = resultService;
}
// #RequestMapping(value = "/search", method = RequestMethod.GET)
#RequestMapping(value ="/template", method = RequestMethod.GET)
public String getPersonList(ModelMap model) {
System.out.println("We are coming into this place");
return "header";
}
#RequestMapping(value = "/number", method = RequestMethod.POST, params = { "regNo" })
public String getStudentResult(#RequestParam(value = "regNo", required = true) String regNo, ModelMap model){
//Server side validation
if(regNo.equals(null) || regNo.isEmpty()){
model.addAttribute("nullValue", "Register Number field cannot be empty");
return "header";
}else if(regNo.length() != 12 ){
System.out.println("This Sys out is shown");
model.addAttribute("invalidLength", new String("invalid"));
return "header";
}else{
model.addAttribute("studentResult",resultService.getStudentResult(regNo));
return "numberResult";
}
}
}
header.jsp
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<head>
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
#mycontainer, h1, h3 {
text-align:center;
}
form {
display:inline-block;
}
/* #regNoErrorMsgNumber {
display: none;
background: brown;
color: white;
} */
</style>
</head>
<body>
<div id="mycontainer">
<form method="post" action="number" id="number">
<!-- <div id="regNoErrorMsgNumber">Only numbers are allowed</div> -->
<div style="text-align: center;" >
<!-- //TODO: Only number, no spaces, no special symbol and 12 digit check-->
<input width="20" type="text" data-validation="numbers" id="regNo" name="regNo" size="30" maxLength="50" placeholder="Enter Register Number"> <b>OR</b>
<div>
<c:if test="${not empty nullValue}">
<c:out value="${nullValue}"/>
</c:if>
<c:if test="${not empty invalidLength}">
<c:out value="Register Number should be 12 digits"/>
</c:if>
</div>
</div>
</form>
<form method="post" action="name" id="name">
<input type="text" id="studentName" name="studentName" size="30" maxLength="50" placeholder="Enter Student Name"></input>
</form>
</div>
<div style="text-align: center;">
<input id="inputFields" type="button" value="Search" />
</div>
<!-- </form> -->
<script>
$(document).ready(function(){
$('#inputFields').click(function(event){
if (document.getElementById('regNo').value !=""){
$("#number").submit();
}else if(document.getElementById('studentName').value !=""){
$("#name").submit();
}
});
});
</script>
</body>
The following piece of jstl code in jsp doesn't work
<c:if test="${not empty invalidLength}">
<c:out value="Register Number should be 12 digits"/>
</c:if>
Also if I use the c:out statement without c:if tag, then it works. But it misaligns two input fields in UI. You can see the div mycontainer code in jsp. I want the error message to be shown below the regNo input field, but at the same time regNo and studetnName input field should be center aligned in a single line.
PS: I get Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core". Try increasing the version of the Dynamic Web Module project facet, as this method of reference may not be supported by the current JSP version (1.1)., but c:out tag with being wrapped with c:if works.
please try the following :
if you are using maven , add this to your dependencies and maven will add the jar for you :
<dependencies>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
if you are not using maven add the jstl library to your project (jstl-1.2.jar)
make sure you set a Targeted Runtime for your project , Tomcat , Glassfish , etc ...
and please refer to this question here .
for the errors part , use the <form:errors> from spring form tags :
- first add the following to your page :
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
then use the form:errors like the following :
<form:errors path="userName" cssClass="error" element="div" />
please refer to the following tutorials , here and here .
Hope that helps
I created a new class called ProjectErrors and I changed the code as follows
if(regNo.equals(null) || regNo.isEmpty()){
univErrors.setHasError(true);
model.addAttribute("isNull", univErrors );
}else if(Pattern.matches("[a-zA-Z]+", regNo)){
univErrors.setHasError(true);
model.addAttribute("onlyNumbers", univErrors );
}else if(regNo.length() != 12 ){
univErrors.setHasError(true);
model.addAttribute("length", univErrors );
}
I changed the jsp like this
<c:if test="${length.hasError}">
<c:out value="Register Number should be 12 digits."/>
</c:if>
<c:if test="${onlyNumbers.hasError}">
<c:out value="Register number can contain only digits."/>
</c:if>
And my error class looks like this
public class ProjectErrors {
public Boolean hasError;
public ProjectErrors(boolean b) {
// TODO Auto-generated constructor stub
hasError = b;
}
public Boolean getHasError() {
return hasError;
}
public void setHasError(Boolean hasError) {
this.hasError = hasError;
}
}
Now I see c:if tag working.
But, still get the warning in jsp "Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core". Try increasing the version of the Dynamic Web Module project facet, as this method of reference may not be supported by the current JSP version (1.1).",