Thymeleaf nested condition in th:with - thymeleaf

I would like to do sommeting like that:
<div id="header_nav" th:fragment="header_nav (someId)" th:with="navPrefix=${'/content' + (someId ? ('/'+someId) : '')"}">
and use it later as *{navPrefix} within the div. I somehow don't get it with the condition nesting.
Can anyone help me?
Thanx!

I suspect this is because you're using th:include when you use the fragment. According to the Thymeleaf Documentation th:include simply includes the fragments content:
Whereas th:include will include the contents of the fragment into its host tag, th:replace will actually substitute the host tag by the fragment’s
If you're using th:include then your th:with won't be getting included, so it will always be blank. You can observe this with other attributes in the same element as the th:fragment declaration, such as style.
You can get around this by using th:replace instead, which will swap the entire fragment, not just the contents. Or, you can wrap your fragment contents with a th:block which you can use to define navPrefix:
<div th:fragment="header_nav(someId)">
<th:block th:with="navPrefix = ${'/content' + (someId != null ? ('/' + someId) : '')} ">
... contents of fragment ...
</th:block>
</div>

The only issues I see are the extra double quotes at the end, and your ternary operator doesn't contain a boolean expression when you pass in a String.
The following works to display either the prefix or the passed parameter within the block:
<div id="header_nav"
th:fragment="header_nav(someId)"
th:with="navPrefix = ${'/content' + (someId != null ? ('/' + someId) : '')} ">
<div th:text="${someId}"></div>
<div th:text="${navPrefix}"></div>
</div>

Related

Make <p> appear and dissapear in Thymeleaf according to variable

Hello I am building an application in Spring Boot and Thymeleaf and I have a paragraph that I want to make it appear only if it has a value. If it does not I do not want it to appear.
Here is the code that I have tried:
<h2 th:text="'Raspuns: ' + ${raspuns}" th:disabled="${raspuns}==null"></h2>
But when I enter the page it says: Raspuns: null I want to make that dissapear.
try this:
<h2 th:if="${raspuns} != null" th:text="'Raspuns: ' + ${raspuns}"></h2>
see more about conditions in the documentation:
Thymeleaf Conditional Evaluation

Escaping ampersand in custom attribute using Thymeleaf 3?

Is it possible to do basic escaping (of ampersand, in my case) when generating a custom attribute? I have tried many ways (with normal escaping, th:text, th:utext, th:attr for all the dynamic attributes, substituting a custom tag in my Spring code), unfortunately found just some workaround, which is listed below.
Basically, it's about an AngularJS application with a piece of Thymealeaf 3 template:
<script th:inline="javascript">
function customSubmit() {
/*<![CDATA[*/
return /*[(${DIALOG_NAME} + '.$valid && submit()')]*/ null;
/*]]>*/
}
</script>
<form th:name="${DIALOG_NAME}"
th:action= "'/' + ${MODULE} + '.' + ${DIALOG_NAME}"
th:ng-app="${DIALOG_NAME} + 'App'"
th:ng-controller="${DIALOG_NAME} + 'Controller'"
ng-submit="customSubmit()"
...
>
...
</form>
What I am trying to make is one construct like
th:ng-submit="some Thymeleaf expression"
that generates the custom attribute value with the && within:
ng-submit="someDialog.$valid && submit()"
without any function redirection like in the workaround above.
Beside extending Thymeleaf (I am using SpringStandard dialect), is any straightforward way to generate such strings?
Thank you for any suggestion.
Ampersands (&) should be HTML-escaped in tag attributes so you can do it like this:
th:attr="ng-submit='some thymeleaf with && in it'"
EDIT:
If you also want to reference a value of some model attribute in the final form attribute value you have to use the expression preprocessing like this:
<form th:attr="ng-submit='__${DIALOG_NAME}__' + ' some ampersand && in it'">
</form>

Razor syntax isn't recognizing '#' after an underscore

I am trying to do the following:
#foreach(var p in #Model.line_products){
<img class="small_img_#Model.line_products[i].short_name" src="/Content/images/#Model.line_products[i].image_name" />
}
Which isn't working, it renders the text just the way it is, not recognizing the '#'. I found this other post in Stackoverflow, which suggests adding parenthesis in the following way:
#foreach(var p in #Model.line_products){
<img class="small_img_(#Model.line_products[i].short_name)" src="/Content/images/#Model.line_products[i].image_name" />
}
Using this workaround, I get that my id is rendered as small_img_(MODEL ATTRIBUTE). Isn't there a workaround which doesn't require adding specific characters? (such as the parenthesis).
You have more errors than a simple undercore problem here. You cannot use #Model inside your if. You are already in a # block. Simply use #foreach(var p in Model.line_products).
Plus, the way you wrote the parenthesis, they will get rendered. What you want is
small_img_#(Model.line_products[i].short_name)
Put the parenthesis after the # instead of before:
class="small_img_#(Model.line_products[i].short_name)"
I sometimes put a couple of Guids in the id of an element and an underscore separator doesn't work.
There are two ways around this. First use the entity code _ instead and secondly just use a hyphen.
<input id="chk_#classLeader.ClassLeader_#ing.Ingredient.Guid" type="checkbox" class="chk_Done form-check">
<input id="chk-#classLeader.ClassLeader-#ing.Ingredient.Guid" type="checkbox" class="chk_Done form-check">
This is because I want to grab out the Guid's when the check box is clicked with some JQuery like this:
$(".chk_Done").click(function () {
var obj =[];
const itemId = ($(this).attr("id"));
const myArray = itemId.split("_");
var ClassLeaderGuid = myArray[1], IngredientGuid = myArray[2];

BeautifulSoup: parse only part of the page

I want to parse a part of html page, say
my_string = """
<p>Some text. Some text. Some text. Some text. Some text. Some text.
Link1
Link2
</p>
<img src="image.png" />
<p>One more paragraph</p>
"""
I pass this string to BeautifulSoup:
soup = BeautifulSoup(my_string)
# add rel="nofollow" to <a> tags
# return comment to the template
But during parsing BeautifulSoup adds <html>,<head> and <body> tags (if using lxml or html5lib parsers), and I don't need those in my code. The only way I've found up to now to avoid this is to use html.parser.
I wonder if there is a way to get rid of redundant tags using lxml - the quickest parser.
UPDATE
Originally my question was asked incorrectly. Now I removed <div> wrapper from my example, since common user does not use this tag. For this reason we cannot use .extract() method to get rid of <html>, <head> and <body> tags.
Use
soup.body.renderContents()
lxml will always add those tags, but you can use Tag.extract() to remove your <div> tag from inside them:
comment = soup.body.div.extract()
I could solve the problem using .contents property:
try:
children = soup.body.contents
string = ''
for child in children:
string += str(item)
return string
except AttributeError:
return str(soup)
I think that ''.join(soup.body.contents) would be more neat list to string converting, but this does not work and I get
TypeError: sequence item 0: expected string, Tag found

How to use or use not a tag basing on a condition in ASP.NET MVC3?

How could I correctly use the following?
{ bool submitter = value; }
...
#(submitter ? "" : #"<a href=""" + Url.Action(actionName, "Queue") + #""">")
<div>
...
</div>
#(submitter ? "" : "</a>")
My error is that the anchor tag definition is being outputed like it should be in a HTML code right to the web browser and instead of seeing a link around the <div> I see the <a href="... etc.
Why?
If you don't want that encoded, then you need to use the Raw extension method:
#Html.Raw(submitter ? "" : #"<a href=""" + Url.Action(actionName, "Queue") + #""">")
<div>
...
</div>
#Html.Raw(submitter ? "" : "</a>")
This is because you cannot put block level elements, like div, inside inline elements like a, unless you use HTML5. I guess from your description you aren't.
If you're checking in a browser DOM inspector, you will see your code looks something like this:
<div></div>
<div></div>
<a></a>
The alternative is to change your div to span and set display: block on it in CSS if you require.
Also, that kind of logic would be better placed in a ViewModel.
Solution that I've: found
#(new MvcHtmlString(#"blah blah"))

Resources