Spring boot: thymeleaf not returning fragments correctly

I am creating a spring bootable web application. For template purposes, I am using thymeleaf. I am creating a separate snippet of an html page and I am creating two different layouts from these snippets. However, when I connect the content page, I am not getting the proper output.

Please check the code snippets /

view resolver

@Configuration
@EnableAutoConfiguration
@PropertySource("classpath:application.properties")
public class WebConfig extends WebMvcConfigurerAdapter {

@Bean
public TemplateResolver templateResolver() {
    ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
    templateResolver.setPrefix("/WEB-INF/views/");
    templateResolver.setSuffix(".html");
    templateResolver.setTemplateMode("html5");
    return templateResolver;
}

@Bean
public SpringTemplateEngine setTemplateEngine() {
    SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
    springTemplateEngine.setTemplateResolver(templateResolver());
    return springTemplateEngine;
}

@Bean
public ViewResolver viewResolver(){
    ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
    viewResolver.setTemplateEngine(setTemplateEngine());
    viewResolver.setOrder(1);
    return viewResolver;
}

      

Directory structure

src/
  main/
    webapp/
        WEB-INF/
            views/
                fragments/
                         header.html
                         footer.html
                         navBar.html
                layouts/
                         appLayout.html
                         baseLayout.html
                 welcome.html

      

appLayout.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

<head>
</head>
<body>

<div th:replace="/fragments/header :: header"></div>
<div th:replace="/fragments/navbar :: navbar"></div>
<div class="container">
    <div layout:fragment="content">
    <p>Content goes here...</p>
    </div>
    <footer>
    <div th:replace="/fragments/footer :: footer"></div>
    </footer>
</div>
</body>
</html>

      

Footer footer.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
    <div th:fragment="footer">
    Footer
    </div>
</body>
</html>

      

Various fragments are created with this method.

aka startup main method class

@ComponentScan(basePackages={"xyz.abc"})
@SpringBootApplication
public class AppApplication {

    public static void main(String[] args) {
        System.out.println("Started");
        SpringApplication.run(AppApplication.class, args);
    }
}

      

welcome.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~{layouts/appLayout}">

<head>
</head>

<body>
<th:block layout:fragment="content">
    <div class="hero-unit">
    <h1>My Content</h1>
    </div>
</th:block>
</body>
</html>

      

Now when I access the server, I get nothing welcome.html

but nothing from appLayout

andfragments

What am I missing?

Another problem I went through many projects and some keep views

under src/main/resource

and I keep it under src/main/web/WEB-INF

what is the difference between these two approaches?

+3


source to share


2 answers


Here's a complete example.

Gradle Dependency:

compile('org.springframework.boot:spring-boot-starter-thymeleaf')

      

If you want to use spring-free dialect [optional] add this:

  compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity4:2.1.2.RELEASE")

      

In SpringBoot you don't need to look at the config, all your views should go: src / resources / templates

enter image description here

Does this mean that all views in the template directory are public?
Not.

Where do I put my public static files (js and css)?
Src / resources / templates / static

How do I create layouts?

Thymleaf makes it easy to handle the vertical and horizontal relationships of image slices.

1. Ratio of vertical layout:

Say you have a master page where you include all your common js and css files, third party nav, nav app bar ... etc. This point of view will vertically enter almost all of yours so in this case you want to somehow embed all of your views within your home page. Let's say you have an employee_list page; when a user requests the employee_list page, the employee_list page will be inserted into your main layout and the user will see the employee_list page + main page items.

Master Page:
On this page, all you have to do is add layout:fragment="content"

. content

is the name of the child view fragment that will be embedded in this page.



<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      xmlns:sec="http://www.w3.org/1999/xhtml">
<head>

</head>

<body>

    <div id = "page_wrapper">

        <div id="side_menu">
            <!--side menu content-->
        </div>


        <div id="content_wrapper">

            <!--page content-->
            <div layout:fragment="content">

            </div>

        </div>

        <script type="text/javascript" th:inline="javascript">

           //common js here

            /* ]]> */

        </script>

    </div>

</body>

</html>

      

enter image description here

Employee list page:
To put the employee_list page in master, all you have to do is add layout:decorator="layouts/master"

to the html

page tag . I put all my layouts in the src / resources / templates / layouts directory, so I use layouts / master instead of just saying master. Also notice the attribute layout:fragment="content"

; this attribute indicates what will be embedded in the master page in this view.

 <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org"
          xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
          layout:decorator="layouts/master">

    <body>

        <div id = "content" class = "content layout-list" layout:fragment="content">

            <div>

               <table>

              </table>

            </div>

        </div>

    </body>

    </html>

      

enter image description here
Result:

enter image description here


Horizontal layout ratio:

What if you want to include a generic view instead of vertical inheritance like in the previous example? Let's say in the above example you want to enable pageview on the employee_list page; in this case, the relationship becomes horizontal.

Snippet of pagination:
This is a working example btw; class Page

is my own custom class that I created to wrap the paged responses. This is a very simple class that I am making, so I put the answer list and pagination information in it. The fragment name is specified usingth:fragment="pagination"

<div th:if = "${page.totalNumberOfItems > 0 and page.numberOfItems > 0}" class = "pagination-wrapper" th:fragment="pagination" xmlns:th="http://www.thymeleaf.org">

    <div class = "valign-wrapper right">

        <div id = "items_per_page_wrapper">

            <div class="valign-wrapper">

                <span  th:text="#{ui.pagination.rows.per.page.label}" style="padding-right: 10px">Rows per page:</span>

                <select  id="items_per_page_select" name = "itemsPerPage">
                    <option th:each="items_per_page : ${page.ITEMS_PER_PAGE_OPTIONS_LIST}" th:text="${items_per_page}" th:value = "${items_per_page}" th:selected="${items_per_page} == ${page.itemsPerPage}">10</option>
                </select>

            </div>

        </div>

        <label  class="current_page_info"
                th:text="#{ui.pagination.current.page.info(${page.currentPageFirstItemNumber}, ${page.currentPageLastItemNumber}, ${page.totalNumberOfItems})}"></label>

        <ul class="pagination right">

            <li th:classappend="${page.pageNumber > 0 } ? '' : 'disabled'">
                <a id="previous_page_link" href="javascript:void(0)">
                    <i class="material-icons">navigate_before</i>
                </a>
            </li>

            <li th:classappend="${page.currentPageLastItemNumber == page.totalNumberOfItems} ? 'disabled' : ''">
                <a id="next_page_link"  href="javascript:void(0)">
                    <i class="material-icons">navigate_next</i>
                </a>
            </li>
        </ul>

    </div>

</div>

      

Employee List Page:
Add this snippet below the table tag.

  <div th:replace="common/pagination :: pagination">
        <!--pagination content-->
    </div>

      

Result:
enter image description here

+1


source


if you are using spring boot you don't need to define a view handler to render html pages.

The @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration, and @ComponentScan. so you probably don't need to define @ComponentScan.

I can also see that you don't need to define those beans if you are using spring boot. the resource template directory is directly accessible without defining beans. so using thymeleaf you can easily get the view from the controller.



Representation

are stored in src / main / web / WEB-INF in spring mvc. but in spring boot views are stored in templates directory which can be returned from controller without any permission configuration.

for your thymelean problem you can see this on github.

https://github.com/sagar1limbu/bookstore

0


source







All Articles