I have a Spring MVC application with thymeleaf.
Depending on a condition tested in the controller method I want to show or hide an html element from the view (input, span, div, button...).
How to do that? For instance, in asp.net you can do myButton.Visible = false (or true) if you want or don't want to display it.
Anything like that available in thymeleaf with spring? Thanks.
You can achieve it by passing the attribute via
org.springframework.ui.Model and use Thymeleaf's th:if attribute
Demo:
package com.example.demo.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
#Controller
public class MealController {
#GetMapping("/order")
public String getCondition(#RequestParam(required = false) String myMeal, Model model) {
model.addAttribute("meal", myMeal);
return "meal/meal-site";
}
}
resources/templates/meal-site.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hot Dog?</title>
</head>
<body>
<div th:if="'hotdog' == ${meal}">A hotdog! 🌭</div>
<div th:if="'hotdog' != ${meal}">Not a hotdog 😢</div>
</body>
</html>
Related
In my Spring Boot Application, I have a HTML Thymeleaf form in which I grab a String Value from the user. I want to pass this value from my Controller Class, to my Service Class and finally in Repo Class. The latter has an #Query and the purpose of this whole implementation is to give users the ability to choose contents from my database based on their input. For example, I have records that vary in different dates. I want user to choose the date that their want and the proper records get displayed from my database.
I have trouble in my controller class in which I need somehow to connect my model and pass it as parameter in my service class. Then the latter should communicate with the Repo Class to execute the query in the #Query and return my results. Until now, all I am getting is null values.
What am I doing wrong???
CONTROLLER CLASS
package com.andrekreou.covid.gov.controller;
import com.andrekreou.covid.gov.model.Covid;
import com.andrekreou.covid.gov.service.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
#Controller
public class WelcomePageController {
private final Service service;
#Autowired
public WelcomePageController(Service service) {
this.service = service;
}
#Value("${welcome.message}")
private String message;
#GetMapping("/")
public String main(Model model){
model.addAttribute("message", message);
return "welcome";
}
#GetMapping("/login")
public String getLoginView() {
return "login";
}
#GetMapping("/date/insert")
public String getDateInsertView() {
return "date-insert";
}
#GetMapping("/show-contents")
public String showAllRates(HttpServletRequest request){
request.setAttribute("covidcases", service.showAllCases());
return "databasecontents";
}
#RequestMapping(value = "/dateInsertion", method = RequestMethod.POST)
public String submit(#ModelAttribute("covid") Covid covid,
ModelMap model,
HttpServletRequest request) {
model.addAttribute("referencedate", covid.getReferencedate());
request.setAttribute("covidcases", service.showCases("referencedate"));
return "databasecontents";
}
}
SERVICE CLASS
package com.andrekreou.covid.gov.service;
import com.andrekreou.covid.gov.model.Covid;
import com.andrekreou.covid.gov.repository.CovidRepo;
import org.springframework.beans.factory.annotation.Autowired;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
#org.springframework.stereotype.Service
#Transactional
public class Service {
private final CovidRepo covidRepo;
#Autowired
public Service(CovidRepo covidRepo) {
this.covidRepo = covidRepo;
}
public List<Covid> showAllCases(){
return new ArrayList<>(covidRepo.findAll());
}
public List<Covid> showCases(String referencedate){
return new ArrayList<>(covidRepo.findByReferencedate(referencedate));
}
}
REPO CLASS
package com.andrekreou.covid.gov.repository;
import com.andrekreou.covid.gov.model.Covid;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface CovidRepo
extends JpaRepository<Covid,Integer> {
#Query("select e from #{#entityName} e where e.referencedate = ?1")
List<Covid> findByReferencedate(#Param("referencedate") String referencedate);
}
THYMELEAF VIEW
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>login</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous">
<style>
body {
background-color: #3e3e3e;
color: white;
}
</style>
</head>
<body>
<div class="container">
<form class="form-signin" method="post" action="/dateInsertion" th:object="${covid}">
<h2 class="form-signin-heading">Please Choose The Date</h2>
<p>
<label for="referencedate" class="sr-only">Username</label>
<input type="text" id="referencedate" name="referencedate" class="form-control" placeholder="referencedate" required=""
autofocus="">
</p>
<button class="btn btn-lg btn-primary btn-block" type="submit">Set Date</button>
</form>
</div>
</body>
</html>
Thymeleaf is a rendering engine so it has no functionality it performs when you post something to your controller. which means basic form posting applies which in your case would be 1 field named referencedate
Asuming your covid entity has this as variable with valid setter method the error would be in this request.setAttribute("covidcases", service.showCases("referencedate")); line where it should be request.setAttribute("covidcases", service.showCases(covid.getReferencedate()));
If your covid entity does not include this parameter you have to either add it or seperatly add it to your controller function as a #RequestParam String referencedate
I am learning Spring Framework. I added home.html in resources/templates/home.html. But it is not visible when I visit http://localhost:8080. I have the following structure:
taco-cloud\src\main\java\tacos\TacoCloudApplication.java
package tacos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class TacoCloudApplication {
public static void main(String[] args) {
SpringApplication.run(TacoCloudApplication.class, args);
}
}
taco-cloud\src\main\java\tacos\HomeController.java
package tacos;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
#Controller
public class HomeController
{
#GetMapping("/")
public String home()
{
return "home.html";
}
}
taco-cloud\src\main\resources\static\home.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Taco Cloud</title>
</head>
<body>
<h1>Welcome to...</h1>
<img th:src="#{/images/TacoCloud.png}"/>
</body>
</html>
Output
Whitelable error page
localhost:8080/home.html
show home.html
You have to change the location of your home page to be in the static folder :
resources/static/home.html
^^^^^^
instead of
resources/templates/home.html
and specify the extension in your controller :
return "home.html";
^^^^^
else you have to create a view resolver to avoid using extensions and to specify the other locations of your pages take a look at Configure ViewResolver with Spring Boot and annotations gives No mapping found for HTTP request with URI error
You can try this.
#GetMapping("/")
public String home()
{
return "templates/home.html";
}
Check more details
Below are few different ways you can place html files in your project.(Note it is from highest to lowest precedence)
src/main/resources/resources/home.html
src/main/resources/static/home.html
src/main/resources/public/home.html
Go through this to get an idea about spring mvc project structure
just a login HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试的登录页面</title>
<link href="css/mui.min.css" rel="stylesheet" />
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<header class="mui-bar mui-bar-nav">
<h1 class="mui-title">登录</h1>
</header>
<div class="mui-content">
<form id='login-form' class="mui-input-group" action="/front/login">
<div class="mui-input-row" style="padding-right: 14px;">
<input name="phone" type="text" style="width: 66%;" class="mui-input-clear mui-input" placeholder="请输入你的手机号">
</div>
<div class="mui-content-padded">
<button id='login' class="mui-btn mui-btn-block mui-btn-primary" type="submit" >登录</NOtton>
</div>
</form>
</div>
<script src="js/mui.min.js"></script>
</body>
</html>
the action is here
package com.neu.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.neu.beans.Userlist;
import com.neu.service.FrontCheckService;
#Controller
public class FrontLoginHandler {
#Autowired
private FrontCheckService service;
#RequestMapping(value = "/front/login")
public String frontlogin(HttpServletRequest request,HttpServletResponse response)
{
//请求和响应的信息都不应该被存储在对方的磁盘系统中;
System.out.println("....servlet....frontlogin()......");
System.out.println("....servlet....frontlogin()......");
System.out.println("....servlet....frontlogin()......");
System.out.println("....servlet....frontlogin()......");
System.out.println("....servlet....frontlogin()......");
//从数据库查找是否存在这样一个手机号的用户
//如果存在那么就取出来 返回
//如果不存在那么就 写入一个
String phone=request.getParameter("phone");
if(service.check(phone)==null)
{
Userlist user=new Userlist();
user.setTel(phone);
user.setUname(phone);
user.setOpenid(phone);
user.setUserimg("default.jpg");
adduser(user);
System.out.println(user.getTel());
HttpSession session=request.getSession();
session.setAttribute("user", user);
System.out.println("存入session成功!");
return "forward:index.html";
//如果为空 捏造一个用户 返回 并 写入数据库
}
else
{
Userlist user= service.check(phone);
System.out.println(user.getTel());
HttpSession session=request.getSession();
session.setAttribute("user", user);
System.out.println("存入session成功!");
return "forward:index.html";
//如果不为空 那就将返回的对象返回
}
}
public void adduser(Userlist user)
{
String phone= user.getTel();
service.insert(phone);
}
}
the question is that when I input a phone number for the first time, login is successful, and it get's the right username . and when I surf the page again and submit with another phone number. its ok .but the third time with another phone number login the username is named before.
I check the eclipse console find the third time request didn't send to the action, because of the several "System.out.println()" didn't print.
the get name page is a page with ajax to get another action to return the "user" attribute of session.
I think you have a browser-caching issue here. Try disabling the cache for your particular request with e.g.:
response.addHeader("Cache-Control", CacheControl.noCache().getHeaderValue());
There are many issues in your application design.
Use Post method to post information from client side to server.
<form id='login-form' class="mui-input-group" action="/front/login" method="post">
You are not invalidating the session created by first or second user.Session management is spring is necessary to handle login from multiple users.
Use cache control headers at your global configuration or on your jsp / html page. though some browser doesnt honor the headers setting.
I have created a managed bean that searches a gene database currently it only returns the result to the glass fish console. I am wondering if anyone can offer any suggestions on how to get my search results to display into my gene/protein search tab.
My current set of code:
MainPage.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<!-- this allows the page to see the welcomepage style sheet-->
<link rel="stylesheet" type="text/css" href="Group1/welcomepage.css" media="screen"/>
<title>Main Page</title>
<!-- allows the page to see the jquery function see "http://jquery.com/" for description -->
<script src="jquery-1.11.0.min.js" type="text/javascript"></script>
<!-- allows the page to see the js script tabs see file for detailed comments-->
<script type="text/javascript" src = "tabs.js"></script>
</head>
<body>
<!-- the wrapper places everyting in one frame so the objects do not move when browser size is altered-->
<div id ="wrapper">
<div id = "main">
<div id ="header">
<!-- again the logo this one will appear in the header in the top left and when clicked returns you to the home page -->
<a href="index.xhtml">
<img id ="logo1" alt="Group1 logo"/>
</a>
<!-- this is the single search bar and button the "this.select()" function selects all the content in the search box in one click-->
<form name="Search" onsubmit="#{SearchUniprot.query}">
<input type="text" id ="GeneralSearch" name="Search" value="#{SearchUniprot.userSearch}" onclick="this.select();"/>
<input type="submit" id ="subSearch" value="Search" name="GenSearchButton"/>
</form>
</div>
<!-- tab container this created the tabs according the to style set out in the CSS -->
<div id="tab-container">
<ul class="tab-menu">
<li id="Start" class="active">Start</li>
<li id="Genes">Genes/Proteins</li>
<li id="Litrature">Litrature</li>
<li id="Analysis">Analysis</li>
</ul>
<div class="clear"></div>
<!-- each div section below determines what is written in each tab -->
<div class="tab-top-border"></div>
<div id="Start-tab" class="tab-content active">
<h1>Recent Activiy</h1>
<p>Recent files will be shown here</p>
</div>
<div id="Genes-tab" class="tab-content">
<h1>Genes and Proteins</h1>
<p>Results for genes and proteins based on search </p>
</div>
<div id="Litrature-tab" class="tab-content">
<h1>Litrature</h1>
<p>Results of Litrature search will be shown here</p>
</div>
<div id="Analysis-tab" class="tab-content">
<h1>Analysis</h1>
<p>A type of analysis will be shown here</p>
</div>
</div>
</div>
</div>
</body>
</html>
SearchUniProt.java
package TestGeneSearch;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
#ManagedBean (name ="SearchUniprot" )
#RequestScoped
public class SearchUniprot {
String userSearch;
public String getUserSearch() {
return userSearch;
}
public void setUserSearch(String userSearch) {
this.userSearch = userSearch;
}
public SearchUni getQuery() {
// make a new object of the SearchUniProt class and set the search term - obviously we need to read this in from the user in a demo
SearchUni query = new SearchUni("tuna");
//run the RunQuery method in SearchUniprot
query.RunQuery();
return query;
}
public SearchUniprot() {
}
}
SearchUni.java
package TestGeneSearch;
import javax.ejb.Stateful;
import uk.ac.ebi.webservices.axis1.stubs.ebeye.EBISearchService_PortType;
import uk.ac.ebi.webservices.axis1.stubs.ebeye.EBISearchService_Service;
import uk.ac.ebi.webservices.axis1.stubs.ebeye.EBISearchService_ServiceLocator;
#Stateful
public class SearchUni {
// Add business logic below. (Right-click in editor and choose
// "Insert Code > Add Business Method")
//searchterm = what you want to search for
private String searchterm;
public SearchUni() {
}
//constrcutor
public SearchUni(String s) {
searchterm = s;
}
public String[] RunQuery() {
try {
//set up to connect to the searchservice
EBISearchService_Service service = new EBISearchService_ServiceLocator();
EBISearchService_PortType srvProxy = service.getEBISearchServiceHttpPort();
// Get the number of results for the query - we don;t necessarily need this but it may be useful
int result = srvProxy.getNumberOfResults("uniprot", searchterm);
System.out.println(result);
//get all results IDs - can easily limit it to however many we want
String[] ids = srvProxy.getAllResultsIds("uniprot", searchterm);
for (int i = 0; i + 1 < ids.length; i++) {
System.out.println(ids[i]);
}
//get more fields - the fields we can get depend on the database to be searched.
//a note about protein names in Uniprot - Uniprot contains two sections, reviewed and unreviewd
//the reviewed entries will have a Reccomended Name (descRecName), the unreviewed entries will have
//a Submitted name (descSubName) - so each of our results will have either a descRecName or a descSubName
//but not both.
//gene name (gene_primary_name) may be null
//accession number (acc) is a stable identifier - the id field printed out above is not the same as an
//accession number and shouldn't be assumed to be stable
String fields[] = {"acc", "descRecName", "descSubName", "gene_primary_name", "organism_scientific_name"};
String[][] results = srvProxy.getResults("uniprot", searchterm, fields, 1, 100);
for (int i = 0; i < result; i++) {
for (int j = 0; j < fields.length; j++) {
System.out.println(results[i][j]);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
}
You're only seeing the results in the console because you're just printing the results in this line
System.out.println(ids[i]);
What you need to do is to store this results somewhere, make them available to your managed bean (for example, storing in a managed bean attribute) and make this information available in your xhtml via this attribute getters and setters.
One thing that is not clear to me yet is why do you need a stateful EJB for this task. If the only thing you need is to query the database and show the results, you may prefer to use a stateless EJB instead, which is simpler and probably will perform better too.
I also suggest you to use some JSF frontend library such as primefaces, so you'll have a whole set of rich GUI elements ready to use. In your specific case, since you're dealing with genomic data, some results (I guess) can be quite big and you may want to use some lazy loading features that are trivial to do with primefaces (and not so trivial to do without it)
The logic is like this
xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<h:form>
<p:inputText id="criteria" value="#{myMB.criteria}"/>
<p:inputText id="result" value="#{myMB.result}"/>
<p:commandButton value="query" action="#{myMB.query}" update="result"/>
</h:form>
</h:body>
</html>
when you hit the query button, myMB.query() method will be called, with the myMB.criteria populated in your managed bean, that may look like this
package mypackage;
import java.io.Serializable;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class MyMB implements Serializable{
private static final long serialVersionUID = 1L;
private String criteria;
private String result;
#EJB
private MyEJB myEJB;
public void query(){
this.result = myEJB.query(this.criteria);
}
public String getCriteria() {
return criteria;
}
public void setCriteria(String criteria) {
this.criteria = criteria;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}
notice that I use here a stateless EJB like this
package mypackage;
import javax.ejb.Stateless;
#Stateless
public class MyEJB {
public String query(String criteria) {
//do your query here
return "xyz";
}
}
after the query is done, the result will go to myMB.result, but it will only be shown after the xhtml process the
update="result"
notice that "result" in the line above is not myMB.result, but the xhtml tag with id="result"
I hope it's clearer now.
Started learning Wicket after ASP.NET MVC and feel a little bit confused about managing its URLs. Here's the code:
Application:
package com.test.wicketapp1;
import org.apache.wicket.protocol.http.WebApplication;
public class WicketApplication extends WebApplication {
public WicketApplication() {
mountPage("/page1", HomePage.class);
mountPage("/page2", Page2.class);
}
#Override public Class<HomePage> getHomePage() {
return HomePage.class;
}
}
HomePage:
package com.test.wicketapp1;
import java.io.IOException;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.WebPage;
public class HomePage extends WebPage {
private static final long serialVersionUID = 1L;
public HomePage(final PageParameters parameters) throws IOException {
BookmarkablePageLink<Page2> bookmarkablePageLink = new BookmarkablePageLink<Page2>("gopage2link", Page2.class);
add(bookmarkablePageLink);
}
}
HomePage markup:
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<title>Apache Wicket Quickstart</title>
</head>
<body>
go page 2
</body>
</html>
What I wanted to have is pretty simple. I expected that there would be 2 urls: "/page1" for HomePage.class and "/page2" for Page2.class, then my HomePage has a link that navigates to Page2 and when HomePage is rendered, that link should have an URL of "/page2".
When I run the application and go to home page, it is rendered like this:
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<title>Apache Wicket Quickstart</title>
</head>
<body>
go page 2
</body>
</html>
I expected to have something like:
go page 2
instead. What did I miss?
The problem is - I should use app's init method instead of ctor to define the mappings.
have a look at this. It might help
https://cwiki.apache.org/WICKET/request-mapping.html