Thymeleaf template passing objects through forms and get/post mapping - java

I have the following thymeleaf template
<!doctype html>
<html lang="nl" xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments::head(title='Film zoeken')">
<title>Film zoeken</title>
</head>
<body>
<nav th:replace="fragments::menu"></nav>
<form method="get" th:object="${zoekForm}" th:action="#{/film/zoeken}">
<label>
Nummer:
</label>
<span th:errors="*{id}"></span>
<input th:field="*{id}" type="number" autofocus required min="1">
<button>Zoeken</button>
</form>
<th:block th:if="${film}" th:object="${film}">
<dl>
<dt>Titel</dt>
<dd th:text="*{title}"></dd>
<dt>Regisseur</dt>
<dd th:text="*{regisseur}"></dd>
<dt>Uitgekomen op</dt>
<dd th:text="*{releaseDate}"></dd>
<dt>Karakters</dt>
<dd th:each="karakter : *{karakters}" th:text="${karakter}"></dd>
</dl>
<form th:if="not ${score}" th:object="${scoreForm}" method="post"
th:action="#{/film/{id}/score(id=${param.id})}">
<label>
Score:
<span th:errors="*{score}"></span>
<input th:field="*{score}" type="number" required min="1" max="10">
</label>
<button>Bewaren</button>
</form>
<div th:if="${score}">
Je score voor deze film is <strong th:text="${score.score}"></strong>
</div>
</th:block>
</body>
</html>
I have two #GetMapping methods and then the final #PostMapping.
The first one do a modelAndView.addObject(new ZoekForm(null));, so it shows only the first form.
Then, the second getmapping do a thing with the content (it shows the film data) and then it has a
modelAndView.addObject("scoreForm", new ScoreForm(null));.
So far the template shows 1) search form for a movie, 2) the film data and finally a field to give the movie a score.
I need to give a score (hit the button from the second form) and show the div
<div th:if="${score}">
Je score voor deze film is <strong th:text="${score.score}"></strong>
</div>
but the website must keep showing the film data. Now, when I hit that score button, all goes away.
It seems like the th:if=${film} is not happening. Clues?
(I assume also that the score object needs to be passed in the post, because if I look up again the same movie, I must be unable to give it a score).

Thymeleaf doesn't create objects for you. You need to pass it the object in your controller. You can either do it in every controller method that returns this template page or just use #ModelAttribute (place it as a method to your controller)
#ModelAttribute("film")
public Film methodNameDoesntMatter() {
return new Film();
}
This will occur on every page reload, so Film object is always new. Make sure there are getters/setters and no arg constructor defined - this is important for thymleaf

Related

How to properly include a jsp in another jsp

I'm making a form to add events to a list but I need to be able to see in that form the previous events from that list. I have a jsp that shows a list of events but it takes an attribute usually added by the controller when you access the list directly from the browser.
So how can I add the list jsp filling that attribute so it shows a list and not just the headers?
I have alreay included the jsp using
<jsp:include page="comp_list.jsp"></jsp:include>
And it shows the headers but as there is no attribute it shows no list. I tried adding attributes to the include like:
<jsp:include page="comp_list.jsp">
<jsp:attribute name="compensaciones">
${compensaciones}
</jsp:attribute>
</jsp:include>
But when I do it it shows an error telling me that this cannot be done.
Also tried params but that would not be the answer for me because params are treated in the controller and not in the jsp itself.
I'm just getting the header of the list which is fine, but i would like to see the list.
Edit: this is how i build the list in case you are wondering
<tbody>
<c:forEach var="comp" items="${compensaciones}">
<td>${comp.getSomething()}</td>
...
</c:forEach>
</tbody>
<jsp:include page="pagename.jsp" />
i thing you are not provide extension in your include tag
Sometimes since I've had prior experience back in the days with HTML and PHP, we simply just would include things like navigation and header for easier management.
I'm unsure for what purpose you're including JSP, but here's an example of how I've done it since I include JSP if a boolean is true.
The site that is accessed:
<div class="row">
<div class="col-lg-2">
</div>
<div class="col-lg-8">
<%
if (loggedin) {
%>
<%# include file="includes/profile.jsp" %>
<% } else {
out.println("<div><h2>You aren't logged in!</h2></div>");
}
%>
</div>
<div class="col-lg-2">
</div>
</div>
And the top and bottom of the JSP file I'm including doesn't contain things like head, title, html, body etc.
<%
User currUser = null;
currUser = (User) session.getAttribute("user");
%>
<div>
<h2>Du er logget ind, velkommen <% out.println(currUser.getUsername().toUpperCase()); %></h2> <br>
<h5>Din Saldo: <b><% if (currUser.getBalance() < 0) { out.println("<font color='red'>" + currUser.getBalance() + "</font>");} else { out.println("<font color='green'>" + currUser.getBalance() + "</font>");} %></b></h5>
<br>
<form class="form" method="post" action="#">
<h4>Oplysninger: </h4>
<h6>
For at ændre oplysninger skal du indtaste dit kodeord!
</h6>
Nuværende Kode: <input type="password" class="form-control" placeholder="kodeord" name="password" required>
<hr>
Email: <input type="text" class="form-control" value="<% out.println(currUser.getEmail()); %>" name="email"> <br>
Brugernavn: <input type="text" class="form-control" value="<% out.println(currUser.getUsername()); %>" name="username"> <br>
<input type="submit" class="btn btn-default" value="Indsend Oplysninger" />
</form>
</div>
When importing JSP into JSP, it's important to know that they will conflict if 1. Duplicate Local Variables. 2. Certain HTML tags aren't correct.
Your intended use seems very complicated to me since I'm not quite understanding it, sorry :3 but if you can't get it working consider to throw it to a session and if it's a one time use then remove it once you used it.
This is working from dacades
<%# include file="../scripts/standard_head_declaration.jsp" %>

JSoup | Fetching part of the HTML

I have problem with fetch site with car ads. I would like to get advertiser's name from it. The main problem is that sometimes that name is showing in different way.
1) Name is Kajetan
(https://www.otomoto.pl/oferta/mercedes-benz-klasa-e-w211-bardzo-dobry-stan-bez-wkladu-finansowego-warszawa-ryki-ID6BEBy9.html#2bd424144f)
<div class="seller-box__seller-info">
<small class="seller-box__seller-registration">Sprzedający na OTOMOTO od 2015</small>
<small class="seller-box__seller-type">Osoba prywatna</small>
<h2 class="seller-box__seller-name"> Kajetan </h2>
</div>
2) Name is AS MOTORS Centrum Pojazdów Używanych KIA
(https://www.otomoto.pl/oferta/kia-ceed-1-6-crdi-136-km-m-bws-fvat-salon-serwis-polska-ID6BHFu3.html#2bd424144f)
<div class="seller-box__seller-info">
<small class="seller-box__seller-registration">Sprzedający na OTOMOTO od 2019</small>
<small class="seller-box__seller-type">Dealer</small>
<h2 class="seller-box__seller-name">
<div class="seller-badge"> <img src="xx.jpg" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="Ten dealer korzysta z pakietu usług Premium Plus" class="">
</div>
AS MOTORS Centrum Pojazdów Używanych KIA
</h2>
</div>
In the first case the solution is easy because I'll do it like this:
public static String fetchOwnerName (String html) {
Elements ownerElement = Jsoup.parse(html).getElementsByClass("seller-box__seller-info").select("h2");
String owner = StringUtils.substringBetween(String.valueOf(ownerElement), "\">", "</h2>");
return owner;
}
But in the second case the problem is that after <h2> there are additional <div> and what is more, name of the advertiser is between <a href="".
How should I change fetchOwnerName method to be universal? I'm using JSOUP library to parse HTML page. Thanks for all of your suggestions.
You can get text inside the h2 tags without worrying about the additional tags i.e div a
You just have to call .text()
Elements ownerElement = Jsoup.parse(html).getElementsByClass("seller-box__seller-info").select("h2");
String owner = ownerElement.text();
This will work if no other text except advertiser's name is present between h2 tags

Call a java function in .jsp when answering a form

I have a .jsp file of a basic chat with a bot, the page is designed as a div that should hold the messages that outcome or income from a form.
The form has one input line that should hold the message.
I want to call a java function that's in a different .java file from the div only after the form is submited
<div id="wrapper">
<div id="menu">
<p class="welcome">Welcome, <b>
<%
if (ctx.isLoggedIn()) //if there is someone in the current session
{
String name = ctx.getName(); // puts the name in the page
out.write(name); // same as last row
}
%></b></p>
<p class="logout"><a id="exit" href="#">Exit Chat</a></p>
<div style="clear:both"></div>
</div>
<div id="chatbox" style="overflow-y: scroll;">
<%
//the place I want to call the function
%>
</div>
<form name="message" action="#" method="post">
<input name="usermsg" type="text" id="usermsg" size="63" oninput="buttonEnabled()"/>
<input name="submitmsg" type="submit" id="submitmsg"/>
</form> <!-- the form that is served -->
</div>
ctx is defined as an object from a class I created
Context ctx = new Context(pageContext);
I tried to call the function like this-
<%
if(request.getParameter("usermsg").toString().length() > 0)// not empty
out.write(ctx.handleMessages());
%>
but It didn't work for some reason.
the function handleMessages() has a queue that contains all of the messages from the server and from the client and returns a String that is already build as an HTML code-
returnedMsg += "<b>"+message.getUser()+"</b> - <a style='color:gray;'>"+message.getTime()+"</a>";
returnedMsg += "<br>";
returnedMsg += "<a>"+msg.getText()+"</a>";
returnedMsg += "<hr>";
So every chat message should look like that-
It would really help me if someone knows how to call handleMessages() from that div when the form is submited.
Thank's ahead.

Do not clear form content upon POST

I am using a Spring form with tabs, each tab again has a form.
The problems are
1)After the form submission, the error messages are displayed but the form content is cleared which should not happen
2)After the form submission the control immediately goes to the default tab which is the first tab in my case. I want the control to stay on current tab after transaction and not go to default tab.
This is the first time I am working using Spring MVC, JSP, jQuery. Please let me know if I have to make any changes.
administrator.jsp
Below is the code for Manage Users tab functionality.
jQuery:
$(document).ready(function() {
$('#btnManage').click(function() {
if($.trim($('#userId').val()) == ''){
$('#area5').html("User Id is a required field.");
}else if($.trim($('#region').val()) == 'NONE'){
$('#area5').html("Region is a required field.");
}else{
$('#manageUserForm').submit();
}
});
$('#btnCancel5').click(function(e) {
$('#manageUserForm').trigger("reset");
$('#area5').html("");
});
});
administrator.jsp:
<div id="tab5" class="tab">
<div class="devices" >
<form:form method="post" id="manageUserForm" modelAttribute="adminUser" action="/DeviceManager/admin/manageUser">
<div align=center class="message" id="area5">${serverError5}</div>
<div>
<div class="plLabelSearch">User Id:</div>
<div class="plinput"><form:input path="userId" type="text" size="29"/></div>
</div>
<div>
<div class="plLabelSearch">Region:</div>
<div class="plselect">
<form:select path="region">
<form:option value="NONE" label="------- Select One -------" />
<form:option value="A" label="A"/>
<form:options items="${regionList}"/>
</form:select>
</div>
</div>
<br>
<br>
<div>
<div class="plLabelSearch"> </div>
<div class="plinput"><a id="btnManage" class="abutton">OK</a></div>
<div class="plinput"><a id="btnCancel5" class="abutton">Cancel</a></div>
</div>
</form:form>
</div>
</div>
You need to re-render the page with the data from the original form submission.
In your case this probably means your form should contain a few hidden fields to allow you to determine which tab you are on, your JSP will need to be able to understand this data and use it to select the appropriate tab.
because you submission is not asynchronous,after you submit,the administrator.jsp is reset,so the error message is display ,owing to this code <div align=center class="message" id="area5">${serverError5}</div>

How to keep dynamicly added controls ater postback? Javascript, JSP

Good Morning all. I have an issue that I am trying to solve but I am stuck, partially due to me not having a full understanding of JSP/ Java platform, and not having a full understanding of what/ how to implement my code in the right way. I do have an ASP background, so I am a bit familiar with some concepts.
The issue I am running into is: I am trying to populate a dynamic label and text box to appear on a webpage (JSP). I have successfully been able to populate the textboxes with a piece of JavaScript code, however, when I submit the form (on Postback) my dynamic controls are gone but all of my static controls are still present. I need to find a way to keep my information in the dynamic control on submit as well. The form does not submit when I have errors but when the form finish rendering all information and dynamic text are all lost.
My Solution: I have decided to use hidden fields to hold this information but I am unable to fire off the hidden fields after form submit: Please have a look below
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<script type="text/javascript">
function validateForm(){
var x=document.forms["myForm"]["fname"].value;
if (x==null || x=="" && document.getElementById('two').value==1){
alert("EMPTY");
document.getElementById('text').style.display = "block";
return false;
}else{
document.myform.submit();
}
}
function display(el) {
if (el.value == "two") {
document.getElementById('text').style.display = "block";
}else {
document.getElementById('text').style.display = "none";
document.getElementById('dynbox').value = '';
}
}
</script>
</head>
<body>
<form name="myForm" action="demo_form.asp" onsubmit="return validateForm()" method="post">
<label >First Name</label> <input type="text"/>
<div>
<input type="radio" name="radio1" id="one" value="one" onchange="display(this);"/>Eligible
</div>
<div>
<input type="radio" name="radio2" id="two" value="two" onchange="display(this);"/>Not Eligible
</div>
<div id="text" class="glassy" name="mytext" style="display:none;">Other: <input type="text" id="dynbox"/>
</div>
<div>
<input type="hidden" name="mytext" value="${mytext}" />
<br></br>
<input type="submit" onclick="validateForm()" value="Submit"/>
</div>
</form>
</body>
</html>
What I am trying to do is select the "Not Eligible" option and type some text in the text box 'mytext' then press submit. Once I press submit, and if the First Name textbox is not filled in, then I want to trigger my hidden textbox so that I won't loose my information in my dynamically created textbox.
I hope this makes sense. I am not sure of how to do in JSP. Can someone give guidance on how to get my expected results? Keeping dynamic controls after Postback?
Thanks in advance.
One thing first: don't let the names Java and Java-Script confuse you. They have (almost) nothing in common. What you are using here is Java-Script only (no Java, no JSP anywhere).
Anyway, I think it is the condition in your validateForm() function that does not work.
I tested it a little bit and it works with these changes:
your form
<form name="myForm" action="test.html" method="get" onsubmit="return validateForm();">
<label >First Name</label> <input type="text" id="firstName"/>
<div>
<input type="radio" name="radio1" id="one" value="one" onchange="display(this);"/>Eligible
</div>
<div>
<input type="radio" name="radio2" id="two" value="two" onchange="display(this);"/>Not Eligible
</div>
<div id="text" class="glassy" name="mytext" style="display:none;">Other: <input type="text" id="dynbox"/>
</div>
<div>
<input type="hidden" name="mytext" value="${mytext}" />
<br></br>
<input type="submit" value="Submit"/>
</div>
</form>
I simply changed the first input and gave it an ID (since I couldn't find the id 'fname' anywhere), so we can access it with JavaScript.
The next thing is your submit button. You had an additional onclick="validateForm()"; there – which indeed calls the validateForm function but does not listen to the returned value (it executes the function.. nothing more). So the onsubmit="return validateForm()" is enough.
your validate function
function validateForm() {
var x = document.getElementById('firstName').value;
if ((x == null || x == "")) {
alert("EMPTY");
// document.getElementById('text').style.display = "block";
return false;
} else {
return true;
}
}
x can now be retrieved by the element's id (which I find easier).. Anyway, the if condition was one of the problems. In your form you set the value of your radio button 'two' to two. But in the if condition you ask if could be 1... which (in my understanding) should never happen. I just removed it to show you that your function works like this. If you want to check the state of the second radio button, you can test it like this:
if(document.getElementById('two').checked == true)
or even better
if(document.getElementById('two').checked)
one last thing: in your else statement, you can simply return true instead of calling submit.. because here:
onsubmit="return validateForm();"
you ask your validateForm() function to give you either true and then submit or false and then stop submitting.
Oh, one last thing (it'S the last, promise): Java and Java-Script handle all && and || in the order: first ´x==null´ would be tested and then x=="" && document.getElementById('two').value==1 would be evaluated together (&& has a stronger binding than ||).. Just for your information :)

Categories