Thymeleaf - How to write Html string literals? - thymeleaf

How can we write HTML and string literals at a same time in Thymeleaf ?
<div class="details"><span class="Section" th:utext="'Sec' <br> ${wind.sec}"></span><span class="Axiom" th:utext="'Axiom' <br> ${wind.axiom}"></span></div>
This throws error
Cannot execute GREATER THAN from Expression "('Sec' < br) > ${wind.sec}". Left is "true", right is "Great"

You can use the following = which uses + for string concatenation:
<div class="details">
<span class="Section" th:utext="'Sec<br>' + ${wind.sec}"></span>
<span class="Axiom" th:utext="'Axiom<br>' + ${wind.axiom}"></span>
</div>
The <br> is just part of the text literal in this case - because you are using th:utext.
However, using unescaped values such as ${wind.sec} is unsafe and is not recommended. There could be harmful values in that variable - especially if the variable holds data provided by end users.
So, unless the following structure change poses a problem, I would recommend something like this:
<div class="details">
<span class="Section" th:utext="'Sec<br>'"></span>
<span class="Section" th:text="${wind.sec}"></span>
<span class="Axiom" th:utext="'Axiom<br>'"></span>
<span class="Axiom" th:text="${wind.axiom}"></span>
</div>
Here we have separated the true text literals (which can use th:utext) from the variables (which should use th:text). Now, any HTML which may have found its way into your ${...} variables will be escaped, rendering it harmless.

Related

thymeleaf evaluate string as variable

suppose I have a thymeleaf fragment named "reference" that takes a parameter referenceNumber="1" and in my model I have "reference1_firstName" = "Bob"
<div ... th:fragment="reference(referenceNumber)">
Reference <div th:text="${referenceNumber}"/> first name is <div th:text="${'reference' + referenceNumber + '_firstName'}".>
</div>
in the obviously incorrect example above I would like to print out "Reference 1 first name is Bob". It seems so simple, I can do it in several other languages, but so far my search has come up empty for thymeleaf
Couple ways to do this.
Preprocessing:
<span th:text="${reference__${referenceNumber}___firstName}" />
#ctx basic object:
<span th:text="${#ctx.getVariable('reference' + referenceNumber + '_firstName')}" />
<span th:text="${#ctx['reference' + referenceNumber + '_firstName']}" />
Or if you intend to access variables this way, use a Map instead of variables.

Thymeleaf - getting locale and comparing

The below should set h1 to HOWDY as the locale is showing en_GB, but it doesn't fall into the case?
Am I doing something wrong here? Thanks
<h1 th:text="${#locale}"></h1>
<div th:switch="${#locale}">
<h1 th:case="'en_GB'">HOWDY</h1>
</div>
When you use Thymeleaf's #locale, you are using a reference to a Java Locale object.
What Works?
The following works the way you expect, because it has already evaluated the Java locale object to its string representation, before evaluating each case statement:
<div th:switch="${#locale.toString()}">
<h1 th:case="'en_GB'">HOWDY</h1>
</div>
The following also works:
<div th:switch="__${#locale}__">
<h1 th:case="'en_GB'">HOWDY</h1>
</div>
In this case, it works because you are using the Thymeleaf preprocessor syntax __${...}__ to force Thymeleaf to evaluate #locale (to its string representation) before it evaluates the remainder of the switch statement.
Additional Explanation
Because Thymeleaf's #locale represents a Java Locale object, you can use any of Locales suitable fields and methods, such as :
<div th:text="${#locale.country}"></div> <!-- a field -->
<div th:text="${#locale.toLanguageTag()}"></div> <!-- a method -->
This is why only using ${#locale} in the Thymeleaf switch statement does not match the 'en_GB' string literal that you are expecting it to match: Thymeleaf is comparing an object to a string.
When you use this...
<div th:text="${#locale}"></div>
...you are again accessing the object itself. But in this case the object will use its toString() method when being rendered by Thymeleaf, before it is displayed - giving you your en_GB displayed value.
However, when you use this...
<div th:switch="${#locale}">
<h1 th:case="'en_GB'">HOWDY</h1>
</div>
...Thymeleaf is using the locale object in the switch statement, not its string representation.

How to apply elvis operator in Thymeleaf?

how to apply a ternary condition that Elvis Operator in Thymeleaf.
I tried this but there is an error showing in IDE. the error Tag start is not closed
<div th:utext="${ed.aurl} ? '<button th:href="#{ed.aurl}" target="_blank" download>View Attachment </button>' : 'No Attachment' "></div>
You shouldn't/can't use HTML in attributes like that (it's expecting a valid HTML doc)... why not write this as regular HTML?
<div>
<button th:if="${ed.aurl}" th:href="#{ed.aurl}" target="_blank" download>View Attachment</button>
<span th:unless="${ed.aurl}">No Attachment</span>
</div>

How to format currency input in RoR + AngularJS app

Sorry for my English.
I need to change input value format, for example: from "1000000" to "1 000 000 $".
In my views of rails app, I have this line of code:
<%= ng_text_field('total_price', 'selected.data.total_price', 'Full price', ng_readonly: '!selected.permissions.update') %>
In helper:
def ng_text_field(name, ng_model, placeholder, options = {})
result = <<-HTML
<div class="form-group" ng-class='{"has-error":errors.#{name}}' #{options[:ng_if] && "ng-if=\"#{options[:ng_if]}\""}>
<label for="#{name}" class="col-sm-3 control-label">#{placeholder}</label>
<div class="col-sm-9">
<input id="#{name}"
type="text"
class="form-control"
name="#{name}"
placeholder="#{placeholder}"
ng-model="#{ng_model}"
#{options[:ng_readonly] && "ng-readonly=\"#{options[:ng_readonly]}\""}>
<p class="help-block small" ng-if="errors.#{name}">{{errors.#{name} | join:',' }}</p>
</div>
</div>
HTML
result.html_safe
end
I am know Angular very little, I have tried some ways and all this ways was incorrect. :(
Could anyone give advice of some help?
Thank you in advance
You're going to need to create a new directive that requires ngModel and applies the appropriate $parser/$formatter to it.
https://docs.angularjs.org/api/ng/type/ngModel.NgModelController#$parsers
A good example of how to do this is (displaying as uppercase but always storing data as lowercase):
ngModel Formatters and Parsers
You should be able to then add the ability to include other directives in your 'options' argument so that they get added correctly to the output.

Capybara - usage of applying has_xpath? on an apath with variable

There is the structure like:
<div class="parent">
<div>
<div class="fieldRow">...</div>
</div>
<div>
<div class="fieldRow">
<div class="CheckBox">
</div>
</div>
<div>
<div class="fieldRow">...</div>
</div>
<div>
<div class="fieldRow">...</div>
</div>
</div>
In my script I am writing a loop for each of the 4 div's under div[#class='parent'] and aiming to click the checkbox if there is, i.e.
members = page.all(:xpath, '//div[#class='parent'])
members.each do |a|
if **page.has_xpath?(a).find(:xpath, "div[#class='fieldRow']/div[#class='CheckBox']")**
a.find(:xpath, "div[#class='fieldRow']/div[#class='CheckBox']").click
end
end
However I can't look for the correct usage of has_xpath? with xpath including variable.
Please advice? Thank you!
has_xpath? takes an XPath expression (not an element) and returns a boolean (true/false) based on whether there are any elements that match that expression within the current scope - http://www.rubydoc.info/gems/capybara/Capybara/Node/Matchers#has_xpath%3F-instance_method. Since it returns true/false you can't then call find on it. For the example you posted there's no need for XPath or checking for the existence of the elements, just find all the matching elements and call click on them. Something like
page.all('div.parent div.fieldRow div.Checkbox').each { |cb| cb.click }
or
page.all('div.parent div.Checkbox').each { |cb| cb.click }
if the fieldRow class isn't something you really need to check.
Note: this assumes clicking the elements doesn't invalidate any of the other matched elements/change the page.
If you REALLY need to do it with the whole members and looping on them , using XPath, and checking for presence then it would be something like
members = page.all(:xpath, './/div[#class='parent'])
members.each do |a|
if a.has_xpath?(:xpath, ".//div[#class='fieldRow']/div[#class='CheckBox']")
a.find(:xpath, ".//div[#class='fieldRow']/div[#class='CheckBox']").click
end
end
Note: the .// at the beginning of the XPath expressions is needed for scoping to work correctly - see https://github.com/teamcapybara/capybara#beware-the-xpath--trap - which is an issue using CSS selectors doesn't have, so you should really prefer CSS selectors whenever possible.

Resources