Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to render thymeleaf fragments #678

Merged

Conversation

johannesg
Copy link
Contributor

This PR adds the ability to return a thymeleaf fragment in a view instead of the whole template. Very useful for tools like htmx.org.

This code takes inspiration from the thymeleaf spring integration, found here

@CLAassistant
Copy link

CLAassistant commented Dec 19, 2023

CLA assistant check
All committers have signed the CLA.

Copy link
Contributor

@sdelamo sdelamo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am interested in improving how to integrate better HTMX with Micronaut Views. And the same for Thymleaf. I use Thymleaf in my pet projects.

However, I am not sure I understand the benefit this PR adds. Currently, I can already render a thymleaf fragment in Micronaut Views template, I do something like:

                    <div th:replace="~{_piecharts :: piecharts(${charts.get(0)})}"></div>

and _piechart.html fragment is something like:

<th:block th:fragment="piechart(chart)" xmlns:th="http://www.thymeleaf.org">
    <div class="chart">
...
</th:block>

@johannesg
Copy link
Contributor Author

@sdelamo You are correct in that you already can render a fragment within a template. What does not work however, is to render only a fragment. For example, these code examples do not currently work:

    public ModelAndView<?> editUser(@PathVariable("id") int id) {
        // ...
        return new ModelAndView<>("users :: editUser", model);
    }
    @Get("/users/{id}/edit")
    @View("users :: editUser")
    public UserModel editUser(@PathVariable("id") int id) {
        // ...
        return model;
    }

This PR adds support for this by parsing the view name and get its fragment selector before sending it to the renderer.

I'm also interested in improving integration with htmx. If this PR gets approved, I might give it a shot.

@sdelamo
Copy link
Contributor

sdelamo commented Feb 14, 2024

@sdelamo You are correct in that you already can render a fragment within a template. What does not work however, is to render only a fragment. For example, these code examples do not currently work:

    public ModelAndView<?> editUser(@PathVariable("id") int id) {
        // ...
        return new ModelAndView<>("users :: editUser", model);
    }
   @Get("/users/{id}/edit")
   @View("users :: editUser")
   public UserModel editUser(@PathVariable("id") int id) {
       // ...
       return model;
   }

This PR adds support for this by parsing the view name and get its fragment selector before sending it to the renderer.

I'm also interested in improving integration with htmx. If this PR gets approved, I might give it a shot.

Sorry for the delay. I set aside to work on this again. @johannesg this works:

https://github.com/sdelamo/button-click-change/blob/master/src/main/java/com/modernfrontendshtmx/HomeController.java#L17-L20

to answer a fragment:

https://github.com/sdelamo/button-click-change/blob/master/src/main/resources/views/htmx.html

The issue you are trying to address it to support the :: syntax. Why would you prefer to use htmx :: message instead of just htmx? to support files with multiple fragments on them?.

@johannesg
Copy link
Contributor Author

@sdelamo Thank you for looking at this.

It's true, if you have one file per fragment, then your example works. However, if you organize multiple fragments in one file, like this:

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Home</title>
</head>
<body>
  <div>MAIN</div>

  <div th:fragment="fragment1">FRAGMENT</div>

  <div th:fragment="fragment2">FRAGMENT</div>
</body>
</html>

And you only want to render "fragment1", then you would need the html :: fragment1 syntax. Just like th:replace does.

@sdelamo
Copy link
Contributor

sdelamo commented Feb 14, 2024

@johannesg can you sign the CLA again?. Sorry for the inconvenience.

@sdelamo sdelamo added the type: enhancement New feature or request label Feb 14, 2024
@johannesg
Copy link
Contributor Author

@johannesg can you sign the CLA again?. Sorry for the inconvenience.

Done

@sdelamo sdelamo merged commit f0a5a4a into micronaut-projects:master Feb 14, 2024
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement New feature or request
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

3 participants