Sightly how to test is a string contain another substring - sightly

in HTL/Sightly, how can I compare an item is in the array? or a string contain a sub string?
Like I have array1(apple, banana, orange), array2(apple,pear)
<div data-sly-list.item=${array1}>
<div data-sly-test=${array2 == item.name}>if match </div>
all other code ...
</div>
so in the above example, only apple will have the extra div

Since version 1.4, you can use in relational operator: https://github.com/adobe/htl-spec/blob/master/SPECIFICATION.md#1143-relational-operators
<div data-sly-test="${item in array2}">if match</div>

Related

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.

Thymeleaf - How to write Html string literals?

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.

Cannot pass model attribute in thymeleaf th:each

I'm trying to iterate over a list and pass the current iteration and another model variable to a fragment, but the "other" model variable is always null.
<div th:each="place : ${results.placeResults}" class="col-sm-6 col-xl-4 mb-5">
<div th:replace="fragments/placecard :: placecard" th:with="place=${place},res=${results}"/>
</div> <!-- end for each-->
In the fragment ${res} is always blank.
I figured it out, the th:replace basically makes the th:with have no effect. I changed the code to use th:include and things look better.

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.

Can I use gr:category in GoodRelations and rdf:type from productontology together?

Can I use gr:category and rdf:type from product ontology together?
I see vso:Canoe from automobile ontology...
<div typeof="gr:SomeItems vso:Canoe" about="#product">
<span property="g:name">ACME Foldable Canoe</span>
<div property="gr:category" content="Outdoors/Boats/Canoes"></div>
</div>
However I'm using productontology,is this possible?
<div about="#myObject" typeof="http://www.productontology.org/id/Canoe">
<div rel="rdf:type" resource="http://purl.org/goodrelations/v1#SomeItems"></div>
<div property="gr:description" xml:lang="en">... a longer description ...</div>
<div property="gr:name" xml:lang="en">.. a short name for the object ...</div>
<div property="gr:category" content="Outdoors/Boats/Canoes"></div>
</div>
Yes, that is well possible and increases a client's ability to understand your data.
So
<div about="#myObject" typeof="http://www.productontology.org/id/Canoe">
<div rel="rdf:type" resource="http://purl.org/goodrelations/v1#SomeItems"></div>
<div property="gr:description" xml:lang="en">... a longer description ...</div>
<div property="gr:name" xml:lang="en">.. a short name for the object ...</div>
<div property="gr:category" content="Outdoors/Boats/Canoes"></div>
</div>
is perfectly valid.
There is currently no official statement from major search engines on the ways they honor additional type information, but it is a safe assumption that
it does not harm adn
the more data of this form is out there, the more it will matter for search engines.
Yes, you can use types and properties from any namespace in RDFa (and RDF in general). In the case of your snippet, you could even get rid of the rdf:type line since #typeof accepts multiple types from any number of namespaces, and those types can be in the form of CURIEs or full URIs (same applies to #property). So your snippet would become:
<div about="#myObject" typeof="http://www.productontology.org/id/Canoe gr:SomeItems">
<div property="gr:description" xml:lang="en">... a longer description ...</div>
<div property="gr:name" xml:lang="en">.. a short name for the object ...</div>
<div property="gr:category" content="Outdoors/Boats/Canoes"></div>
</div>

Resources