pass thymeleaf variable as parameter in method - spring

I concatenate the state and my stateCounter to one String. This is my value for my HashMap which stores all the States but I don't get it to to put this variable in my method.
<span th:with="stateName=${item.state} + ${item.stateCounter}"></span>
<td th:text="${{order.getStateRepository().get(${stateName})}}"></td>

Some notes:
(1) Using a <td> tag suggests you are also using a <table>. Having a <span> tag next to a <td> tag inside a table is not valid HTML (assuming this is what it looks like in your template - maybe this is just a copy/paste thing).
(2) If your order object has a stateRepository field, then you don't need to use a getter order.getStateRepository(). You can just use the field name order.stateRepository. You are already doing this with item.state, for example. Thymeleaf will figure out from the field name how to use the related getter - e.g. item.getState().
(3) The scope (availability/visibility) of a local variable, such as stateName in th:with="stateName=${item.state} is limited to the tag in which it is declared, and also to any sub-tags. You do not have any sub-tags in your <span> - therefore the variable is not visible anywhere outside of your span. So, it is not available inside the <td> tag.
(4) Do you need to use a local variable in your example?
Instead of using get(stateName), you can use the expression referred to by stateName directly:
get(item.state + item.stateCounter)
So overall, this should work (based on the assumptions above):
<td th:text="${order.stateRepository.get(item.state + item.stateCounter)}"></td>
Maybe you do need the local variable, of course. It may depend on the wider context of the Thymeleaf template.

You are trying to use local variable. It will work if you try as follows:
<div th:with="stateName=${item.state} + ${item.stateCounter}">
<td th:text="${order.getStateRepository().get(stateName)}"></td>
</div>

Related

Thymeleaf custom dialect - nested attributes

I would like to ask if it is possible to have nested attributes in HTML tag which can reuse result of previous one. For example
<p custom:one="some text to process" custom:two="process result of custom:one">
where custom:one can be used standalone but custom:two have to be used with custom:one. The final result will be produced by custom:two
if I got you right, you can do it with local variables
You need to specify th:with to declare a variable.
Note that the declared variable is available within the element.
<div th:with="newValue = 'Hello ' + ${val}">
<span th:text="${val}">One</span>
<span th:text="${newValue}>Two</span>
</div>
Let me know if that's what you're looking for.

Hardcoding of path and how to avoid it?

spring-boot-starter-parent 2.3.5.RELEASE
I'm studying a video course. Thymeleaf it used. The lecturer has hardcoded a part of a path.
<a hredf="#" th:href="#{/recipe/show} + ${recipe.id}}">View</a>
Could you tell me whether such hardcoding is Ok? Why didn't they put this path to a variable and didn't pass it to the context?
Is there a way not to hardcode paths?
this kind of links are usually immutable.
like for showing receipts id.
and hard coding them aint a problem.
but if your path can be change, you can change use a variable like what you have done:
${recipe.id}
if you had another variable section in your path you could use variable for them too.
<a hredf="#" th:href="#{/recipe/} + ${actionName} + ${recipe.id}">View</a>
There is some kind of not to hard coding in Spring (JSF) to use ControllerName and Action Name as route name like this:
<h:commandButton action = "#{receiptController.show}" />
or:
<h:commandLink action = "#{receiptController.show}" value = "link text">
<f:param name = "receiptId" value = "${receipt.id}" />
</h:commandLink>
According to : https://www.thymeleaf.org/doc/articles/standardurlsyntax.html
thymeleaf has not implement This Feature.
you can only pass variables to it.
so you can have an static class of Constant url map.

Thymeleaf Template not rendering param value inside th if condition

I am using thymeleaf template for my spring boot application. Here below the main page,
<div th:replace="content :: content"></div>
and inside content fragment,
<div th:fragment="content">
<h4 th:if="${param.val== 'abc'}">SOME-TEXT</h4> // not working
<h4 th:if="${param.val== 'abc'}" th:text="${param.val}"></h4> // not working
<h4 th:text="${param.val}"></h4> // working and value is abc
<h4 th:unless="${param.val== 'abc'}" th:text="${param.val}"></h4> // working - value in html text is abc
<h4 th:unless="${param.val== 'abc'}">SOME-TEXT</h4> // Working, value is SOME-TEXT
</div>
URL: domain/?val=abc
I want to display: SOME-TEXT in html if param.val == 'abc'.
Value 'abc' is coming inside th:text. But inside th:if failing.
Seems some hidden extra strings added to param.val?
Any suggestion?
The Thymeleaf function ${param.val} will return a request parameter called val. But this could be a multivalued object (e.g. an array) - for example consider this (which is a valid construction):
?val=abc&val=def
So to work with a single-valued string, you can do this:
<h4 th:if="${#strings.toString(param.val)} == 'abc'" th:text="'SOME-TEXT-2'">SOME-TEXT-1</h4>
This prints SOME-TEXT-2 in the web page.
Or you can use this:
<h4 th:if="${#strings.toString(param.val)} == 'abc'">SOME-TEXT-1</h4>
Which prints SOME-TEXT-1.
Just out of interest, if you used that first example val=abc&val=def, then you can see what happens with this:
<h4 th:text="${param.val}"></h4>
It prints an array:
[abc, def]
You may see something like this when processing a series of related checkboxes (just as one example).
Update:
For a null-check, using Thymeleaf, you can do this:
<h4 th:if="${param.val} != null and
${#strings.toString(param.val)} == 'abc'">SOME-TEXT-2</h4>
In this specific case, it isn't really needed, as you are not doing anything with the null value which might cause a problem.
It's more relevant if you are chaining values in objects foo.bar.baz - and you need to check if foo or bar are null to avoid a null pointer exception.
Bear in mind that Spring's expression language has the safe navigation operator, which can be very helpful in such cases: foo.?bar.?baz, allowing you to write more concise null handling than with Thymeleaf alone. But again, not relevant to your specific example from the question.

I need to verify whether a label "Annuitant" and its value " RPD" is present or not using parent class

<div class="col-sm-3">
<span>Annuitant:</span>
</div>
<div class="col-sm-3">
<span id="annuitant">
RPD
</span>
</div>
Xpath code that i used previously
findXpath=page.find('label', text: workbook.cell(j,k), :match => :prefer_exact).path
splitXpath=(findXpath.split("/")) #splitting xpath
##Xpath manipulation to get the xpath of "RPD"
count1=splitXpath.count
value1=splitXpath.at(count1-3)
value=splitXpath.at(count1-2)
labelNum=value1.match(/(\d+)/)
i=0
elementNum=labelNum[1].to_i+1
for maxnum in 1..splitXpath.count-4
elementXpath=elementXpath + "/" + splitXpath[maxnum]
end
elementXpath=elementXpath + "/div[" + elementNum.to_s + "]" + "/"+ value
elementXpath=elementXpath + "/" + splitXpath.at(count1-1)
finalElementXpath=elementXpath.sub("label","span")# obtained the xpath of RPD
if (workbook.cell(j+1,k) == (find(:xpath, finalElementXpath).native.text)) # verifying the value RPD is present
Can I use parent class and verify whether "Annuitant" is present and also to check whether Annuitant value is "RPD". Please help me to write a code for this in ruby capybara
Use assert_selector to check if the selector has the text you want. See below:
page.assert_selector('#annuitant', :text => 'RPD', :visible => true)
You can scope Capybara's finders/matchers to any element by either calling them on an element or using within(element) ...
In this case you'd want to scope to at least one level higher in your html document so that both elements you are interested in are contained by the element you're scoping too. Also the class 'col-sm-3' would be a bad choice because it is not going to be unique to these elements. Another thing this comes down to is how rigorous does your check need to be, do you actually need to check the structure of the elements or do you just need to verify the text appears next to each other on the page. If the latter something like
element = find('<selector for parent/grandparent of both elements>') # could also just be `page` if the text is unique
expect(element).to have_text('Annuitant: RPD')
if you do actually need to verify the structure things get more complicated and you would need to use XPath
expect(element).to have_selector(:xpath, './/div[./span[text()="Annuitant:"]]/following-sibling::div[1][./span[normalize-space(text())="RPD"]]')

Why is #Html.Label() removing some characters

When I use the following code in my razor view it renders <label for=""> someText</label> and not <label for="">1. someText</label> but I can't figure out why 1. is removed while rendering.
#Html.Label(String.Format("{0}. someText",1))
Edit:
The following code renders <label for="">1# someText</label> as expected.
#Html.Label(String.Format("{0}# someText",1))
You are misusing the Html.Label method. It is for:
Returns an HTML label element and the property name of the property
that is represented by the specified expression.
That's why it gets confused if you have a point . in the first parameter because it expects a property expression there.
However, you can use the second overload:
#Html.Label("", String.Format("{0}. someText",1))
Or just write out the HTML:
<label>#String.Format("{0}. someText", 1)</label>
You can avoid using the "Html Helper's label" and directly use html "label" and place whatever you want to display correctly. It can also save some time ;)
The syntax which you are using is wrong or We can say that this is not a way to use property with RAZOR syntax.
You ca use this that may be help full for you.
**
#Html.LabelFor(model => model.PropertyName,
String.Format("{0}. " + #Model.PropertyName.ToString() + ",1))
**
I was using this for a data table that contained a double (Lat/Long) and saw this same problem. Thanks for the tips (I am not allowed to comment).
For me, the problem was solved ..
#foreach (var cell in item.ItemArray)
{
<td>
#Html.Label("",cell.ToString().Trim())
</td>
}

Resources