Do thymeleaf fragments need to exist inside a well-formed HTML file? - thymeleaf

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

Related

How to pass a fragment to a message expression in Thymeleaf

Is it possible to pass a fragment to a message expression in Thymeleaf? I want to re-use fragments for creating links in messages.
My fragment looks something like this:
<div th:fragment="link(url, text)" th:remove="tag">
<a th:href="#{${url}}"><span>${text}</span></a>
</div>
and I have a message like that:
home.welcome=Hello User! See new content at {0}.
Now I want to pass the evaluated fragment to the message expression (pseudo-code):
<p th:utext="#{home.welcome(${link:: link(url='myUrl', text='myText')})}"></p>
The resulting HTML should look like this:
<p>
Hello User! See new content at <span>myText</span>.
</p>
I discovered Fragment expressions introduced in Thymeleaf 3 but I'm not sure if they are the way to go.
You can try th:with.
Call fragments like so
<div th:include="fragments/common :: link" th:with="url='www.google.com', text='Click Me'"></div>
This is your fragment
<div th:fragment="link" th:remove="tag">
<a th:href="#{${url}}"><span th:inline="text">[[${text}]]</span></a>
</div>
This is the HTML you will get
<div>
<a href="www.google.com">
<span>Click Me</span>
</a>
</div>

Difference between Thymeleaf include and replace?

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.

How can I create a re-usable custom HTML panel in ASP.NET MVC?

I am trying to create a re-usable UI element in ASP.NET MVC that wraps around whatever content I choose to place in it. My first thought was to create a partial view, but that doesn't seem to help me in what I am trying to accomplish.
The Template
For example I would like to create some re-usable markup similar to this (please excuse the pseudo-code):
<div class="panel panel-default">
<div class="panel-body">
#RenderBody()
</div>
</div>
A Simple Example
Then in my views I would like to do something similar to this:
#Render.Partial("MyPanel")
{
<img src="image.jpg" />
}
Assuming that code worked as expected it would generate the following:
<div class="panel panel-default">
<div class="panel-body">
<img src="image.jpg" />
</div>
</div>
Another Example, with more complex markup
Theoretically I would like to be able place any and everything I would like within one of the panels. So even more complex markup would still appear legible.
#Render.Partial("MyPanel")
{
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
<div class="form-group">
<label for="exampleInputFile">File input</label>
<input type="file" id="exampleInputFile">
<p class="help-block">Example block-level help text here.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Check me out
</label>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
}
Just like in the first example, it would wrap everything inside the header and footer of my template:
<div class="panel panel-default">
<div class="panel-body">
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
.. truncated ..
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
Known Possibilities
Partial View. A partial view seems to make sense, except I have been unable to figure out a way to create a partial that has flexibility beyond the Model it was designed for. I gave two examples, because the contents within my panel could be significantly different each time I use it. I would like to be able throw anything into the body of this partial view; text, markup, more razor code, etc.
HTML Helper. This works great when I have specific parameters I would be passing in. I don't see this as practical when needing to enter large amounts of markup, as it would become hard to read/maintain. Also since html would be passed in as a string, I'm not sure how this would work with razor tags?
2 Partial Views. Using one as the header and the other as the footer. This works, but it just feels sloppy to me.
I was able to do this in ASP.NET WebForms by creating a custom control. It seems like this is something that should be straight forward in MVC too, but I just haven't quite been able to figure out a good solution yet.
You can use "DynamicInvoke" to create html helpers with dynamic markup, such as:
public static IHtmlString CustomPanel(this HtmlHelper htmlHelper, Func<object, object> panelMarkup = null)
{
return CustomPanel(htmlHelper, (panelMarkup == null ? "" : panelMarkup.DynamicInvoke(htmlHelper.ViewContext).ToString()));
}
public static IHtmlString CustomPanel(this HtmlHelper htmlHelper, string content)
{
TagBuilder div = new TagBuilder("div");
div.AddCssClass("panel panel-default");
TagBuilder innerDiv = new TagBuilder("div");
innerDiv.AddCssClass("panel-body");
innerDiv.InnerHtml = content;
div.InnerHtml = innerDiv.ToString();
return new HtmlString(div.ToString());
}
And then you would use it like this:
#Html.CustomPanel(
#<text>
<div>My Custom Markup</div>
<span>More Stuff</span>
</text>
)
Your final content will look like:
<div class="panel panel-default">
<div class="panel-body">
<div>My Custom Markup</div>
<span>More Stuff</span>
</div>
</div>
You see this used often in some 3rd party widget libraries (kendo-ui is the main one i know of)
There are many ways to create reusable content in MVC, but they all have various pros and cons. For instance, custom Html helpers are a common method, but they require writing a lot more code than you probably want.
You can certainly use partial views, just pass a model containing the content you want to render to the partial... but that can also be a little confusing as well.
I think what you may be looking for are Razor Helpers. These are explained in more detail here:
http://weblogs.asp.net/scottgu/asp-net-mvc-3-and-the-helper-syntax-within-razor
However, the basic structure would look like this:
#helper MyHelper(string content)
{
<div class="panel panel-default">
<div class="panel-body">
#Html.Raw(content)
</div>
</div>
}
Then you use it like this:
#MyHelper("<img src="image.jpg" />")
You don't have to use strings, you could use structured content, models, etc.. you can use other helpers inside. You can re-use them as described later in the article.
You might want to start thinking about your pages as more data-centric, however. If you use EditorTemplates to render your data then you render controls based on the type of your data rather than rendering your pages and trying to adapt your pages to contain your data.

How to create a wrapper component / directive?

I have some markup I would like to cover with a simple wrapper. In this case, the idea is to wrap two <input> elements within some markup, so that this markup:
<div class="group-class">
<div class="first-class">
<input id="first">
</div>
<div class="second-class">
<input id="second">
</div>
</div>
would be marked up like this instead:
<my-wrapper>
<input id="first">
<input id="second">
</my-wrapper>
I initially thought of a component, but that would create a shadowDOM, and thus would not behave the same way as if <my-wrapper> didn't exist. <my-wrapper> tag should replace itself with the content of the first example, so that the DOM rendered is the same. I believe I saw some replace option for an angular-directive, but I am very unsure how to do this.

AngularJs not working with dynamic html

In my cshtml file I have a form named 'ApplyMedicalMain' and I want to show a dynamically loaded division when the form is dirty but its not happening even though the form is dirty ...
Below is my code that i got in Firefox Inspect Element:
<form class="form_section ng-dirty ng-valid ng-valid-required" name="ApplyMedicalMain" method="post" action="/MVC/Quote/ApplyMedical">
<div id="Step1_PartialView" class="QuoteStep1">
<script type="text/javascript" src="/Scripts/Renderings/Presales/ApplyMedical.js">
<div name="Conditions" id="conditions_or_symptoms" ng-hide="ApplyMedicalMain.$dirty">
<div class="generic_error_message select">
<div class="error_icn_message"></div>
</div>
As you can see above, I have mentioned ng-hide for the division name='conditions' but it is not getting hidden even though the form has class 'ng-dirty'.And please note that the the division 'conditions' is loaded dynamically from other partial view.
can someone help me ?
You forgot to wrap everything in a 'ng-app' container, here is a working example (I cleaned a bit the code)
<div ng-app>
<form class="form_section ng-dirty ng-valid ng-valid-required" id="ApplyMedicalMain" method="post">
<div ng-hide="ApplyMedicalMain.$dirty">Hidden when dirty</div>
<div ng-show="ApplyMedicalMain.$dirty">Shown when dirty</div>
</form>
</div>
I'm not entirely sure why your example isn't working, but I would suggest you use css to do your hiding/showing rather than using angular's bindings:
form.ng-dirty .hide-on-dirty{
display:none;
}
And then:
<form class="form_section ng-dirty ng-valid ng-valid-required" name="ApplyMedicalMain" method="post" action="/MVC/Quote/ApplyMedical">
<div id="conditions_or_symptoms" class="hide-on-dirty"> ... </div>
</form>
That's a bit more efficient that creating a binding to the form controller's state. But its just a thought. There might be more of a reason why you're wanting to do the binding.

Resources