What is the difference between the two Thymeleaf attributes: th:include and th:replace?
According to documentation if you have this situation:
<div th:include="..."> content here </div>
fragment will be placed inside <div> tag.
However when you use replace:
<div th:replace="..."> content here </div>
then <div> will be replaced by content.
Thymeleaf can include parts of other pages as fragments (whereas JSP
only includes complete pages) using th:include (will include the
contents of the fragment into its host tag) or th:replace (will
actually substitute the host tag by the fragment’s).
Taken from baeldung
There are three basic ways to include content from a fragment:
insert – inserts content inside the tag
replace – replaces the current tag with the tag defining the fragment
include – this is deprecated but it may still appear in a legacy code
Try to understand with this
suppose this the fragment
<div th:fragment="targetFragmentToIncludeInOurPage" id="tagWithFragmentAttribute">
<div id="contentGoesHere"></div>
</div>
we are using this in these div
<div id="tagWithReplaceAttribute" th:replace="fragments/header :: targetFragmentToIncludeInOurPage"></div>
<div id="tagWithInsertAttribute" th:insert="fragments/header :: targetFragmentToIncludeInOurPage"></div>
<div id="tagWithIncludeAttribute" th:include="fragments/header :: targetFragmentToIncludeInOurPage"></div>
So the final output:
<div id="tagWithFragmentAttribute">
<div id="contentGoesHere"></div>
</div>
<div id="tagWithInsertAttribute">
<div id="tagWithFragmentAttribute">
<div id="contentGoesHere"></div>
</div>
</div>
<div id="tagWithIncludeAttribute">
<div id="contentGoesHere"></div>
</div>
Thymeleaf can include parts of other pages as fragments (whereas JSP only includes complete pages) using th:include (will include the contents of the fragment into its host tag) or th:replace (will actually substitute the host tag by the fragment’s). This allows the grouping of fragments into one or several pages.
Related
I'm creating a couple of thymeleaf fragments to use in other pages, and I was told they need to be inside a well-formed html page (with HTML, HEAD, BODY tags etc). Is this the case?
The fragments are only going to be used with th:include/th:replace in other places.
A fragment just needs to be a well formed html. You can start with a div
For e.g
<div th:fragment="formField (field, value, size)">
<div>
<label th:for="${#strings.toLowerCase(field)}"> <span
th:text="${field}">Field</span>
</label>
</div>
<div>
<input type="text" th:id="${#strings.toLowerCase(field)}"
th:name="${#strings.toLowerCase(field)}" th:value="${value}"
th:size="${size}">
</div>
Which you then include somewhere else
<body>
<header th:insert="fragments/general.html :: header"> </header>
<div th:replace="fragments/forms.html
:: formField(field='Name', value='John Doe',size='40')">
</div>
<div th:replace="fragments/general.html :: footer"></div>
I took these examples from here: https://www.baeldung.com/spring-thymeleaf-fragments
I'm a newb working on my first site. I plan on having each page load via ajax in order to have a music player run constant in the background, but I would like back-button functionality so I'm researching how to do that.
Most of the tutorials I'm finding that relate to ajax and pjax are 5-6 years old; I'm just wondering if pjax and the rack-pjax rails gem is still applicable, thanks
You don't need pjax to do this since turbolinks is already capable of this.
Turbolinks allows you to mark certain elements as permanent. Permanent elements persist across page loads, so that any changes you make to those elements do not need to be reapplied after navigation.
<div id="music-player" data-turbolinks-permanent>...</div>
https://github.com/turbolinks/turbolinks#persisting-elements-across-page-loads
Update:
The element that you add data-turbolinks-permanent attribute to, must have an unique ID, otherwise it won't work.
Designate permanent elements by giving them an HTML id and annotating them with data-turbolinks-permanent.
<!-- SEQUENCER MODAL BODY -->
<div class="modal-body" id="music_player_modal" data-turbolinks-permanent>
<div class="container-fluid">
<div class="row">
<div class="col-md-12 nav-index" id="sequencerIndex">
<div id="jp_container_1">
<div class="jp-playlist">
<ul>
<li></li> <!-- Empty <li> so your HTML conforms with the W3C spec -->
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
Before each render, Turbolinks matches all permanent elements by id and transfers them from the original page to the new page, preserving their data and event listeners.
I have the following HTML Markup:
<div id="site-wrapper" class="show-for-large-only">
<div id="site-canvas">
<%= yield %>
</div>
</div>
For Mobile Devices i want an additional section like:
<div class="show-for-small-only">
<%= yield %>
</div>
<div id="site-wrapper" class="show-for-large-only">
<div id="site-canvas">
<%= yield %>
</div>
</div>
With CSS i can hide the divs depending on the user's viewport.
Is there a way to avoid rendering the content of yield twice i.e. only to render the relevant div?
Server doesn't know about clients screen size and available viewport. Unless you specify it in the query string or separate ajax request I think it is impossible to determine.
In your place, I would make an additional ajax get request for desired mobile content.
EDIT:
In your controller, you can determine user-agent by http headers, using request object. I would write a helper for this. Save the result to an instance variable like #is_mobile_agent and in your view you would need an additional if statement before yield. Something like
yield if #is_mobile_agent
I have been developing with MVC for a few years and this is a nagging issue I have encountered several times. I do not like any of the ways I have handled this in the past so I thought I would ask here.
Let's say I have a series of nested DIVs on my view:
<div id="outer">
<div id="inner1">
<div id="inner2">
</div>
</div>
</div>
At runtime I want to add another element, a DIV or anchor, inside of the outer div but have it contain the inner DIVs.
<div id="outer">
<div id="newone">
<div id="inner1">
<div id="inner2">
</div>
</div>
</div>
</div>
How would you recommend handling this?
I imagine this would have more to do with JavaScript than with the server-side code. And since ASP.NET MVC comes with jQuery, you may as well make use of the wrap() function. Something like this:
$('#inner1').wrap('<div id="newone"></div>');
In rails, I'm used to use the yield/content_for to site mesh. (http://guides.rubyonrails.org/layouts_and_rendering.html#using-content_for)
I can't find in Grails documentation a way to do this... Could you help me?
EDIT
Here is the situation:
I have a layout containing this:
<body>
<div id="wrapper">
<div id="container">
<div id="header">
<g:render template="/layouts/header"/>
</div>
<g:render template="/layouts/menu"/>
<div id="container-homepage">
<g:layoutBody/>
<div id="subfooter">
<div id="content">
<div id="left">
<div id="logo_sub_header"></div>
</div>
<div id="right"></div>
</div>
</div>
</div>
</div>
</div>
</body>
And I want to be able to add a html snippet (search tool bar for example) juste above the container-homepage div. A partial could do the trick.. if this search tool bar was always the same. The thing here is that this search bar depends on the page i'm visiting.
I could also just change the position of the container-homepage div to put it directly into the view, and not the layout, but then i'll have to to it in ALL the views, and that's not DRY.
Any ideas?
Regards,
I think you have two solutions:
the g:render tag is the best option if your content block will not change based on a custom page.
Anyway I would take a look ah this link
http://grails.org/Content+Blocks
because g:pageProperty it is the most elegant and flexible solution.
Perhaps the g:render tag is what you're looking for? It allows you to render a template anywhere within your view (including in other templates). You can also pass in a model for the template to use.
Note the section at the bottom of that page on naming conventions -- template view gsp filenames should begin with an underscore (though that underscore is not supplied in the render tag). There's mos def a way to override this, but things work automagically if you put the underscore there.