Thymeleaf classappend for more than two alternatives - thymeleaf

I have a badge used inside the bootstrap card. There are 3 possible values for this badge. FREE, BASE, PREMIUM.
I want to use different colors for these 3 values.
Div class looks like this:
<div class="badge text-white position-absolute" th:text="${content.getCategory()}"></div>
How can I update my class on the fly to use bg-dark for BASE, bg-primary for FREE, and bg-danger for PREMIUM?
I tried to use literal substitutions for th:classappend but I could not find a way to make it work with triple possible values.

You could do it like this:
<div class="badge text-white position-absolute"
th:with="category=${content.category.toString()}"
th:classappend="|${category == 'BASE' ? 'bg-dark' : ''}${category == 'FREE' ? 'bg-primary' : ''}${category == 'PREMIUM' ? 'bg-danger' : ''}|"
th:text="${category}"></div>
This also works by defining an inline map:
<div class="badge text-white position-absolute"
th:with="categoryClass=${ {'BASE': 'bg-dark', 'FREE': 'bg-primary', 'PREMIUM': 'bg-danger'} }"
th:classappend="${categoryClass.get(content.category.toString())}"
th:text="${content.category}"></div>

Related

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.

Thymeleaf Swich with Spring Security

I'm trying to build an eshop. I want to create a page that, when viewed by a User, only shows those items which quantity is greater than 0, but when Administrator viewing the same page, they can see all items and can add/edit/delete items regardless of whether the quantity is 0 or more.
I think maybe I can use Thymeleaf with Spring Security like this:
<div th:switch=sec:authorize="hasAuthority('admin')">
<div th:case="'admin'" class="tilt pic" id="whoKnows" >
<div th:case="'user'" class="tilt pic" th:unless="${viewAvailableWhisky.quantityWhisky} == 0">
but it's not working.
It's a joke? two people edit my text, but they don't know answer...
Two years later.
If you would want to stick to the th:switch approach, this could be a way:
<div th:switch="${#authorization.expression('hasAuthority(''ROLE_ADMIN'')')}">
<div th:case="true" class="tilt pic" id="whoKnows">ADMIN</div>
<div th:case="false" class="tilt pic"
th:unless="${viewAvailableWhisky.quantityWhisky} == 0">USER</div>
</div>
From http://www.thymeleaf.org/doc/articles/springsecurity.html:
The sec:authorize attribute renders its content when the attribute
expression is evaluated to true
Just use sec:authorize directly:
<div sec:authorize="hasAuthority('admin')" class="tilt pic" id="whoKnows"></div>
<div sec:authorize="hasAuthority('user')" class="tilt pic" th:unless="${viewAvailableWhisky.quantityWhisky} == 0"></div>
Your solution doesn't work because your switch condition will resolve to true or false but not to 'admin' or 'user'. hasAuthority('admin') will resolve to true if the user has the 'admin' authority and to false if not.

Conditionally add hide-xs attribute

In an ng-repeat I want to add a hide-xs attribute on an element based on the current scope.
How can I do that?
I basically want to do something like (this obviously don't work):
<li ng-repeat="item in items" hide-xs="{{ item.showAlways ? 'false' : 'true' }}">
{{item.title}}
</li>
Edit
I ended up doing this (as suggested by DieuNQ) but if anybody know how to do it using directive and not class I would take it
<li ng-repeat="item in items" ng-class="{'hide-xs': !item.showAlways }}">
{{item.title}}
</li>
hide-xs not works like that (it does not depend on true or false). It just add class to your tag. Try this:
In your html:
<li ng-repeat="item in items" ng-model="item.showAlways" ng-class="someClass">
...
</li>
In your controller:
$scope.item.showAlways ? $scope.someClass == '' : $scope.someClass == 'hide-xs';

Grails: Removing Unwanted Brackets when Displaying Variable

I have a .gsp page where a student can select a course that they are in. That selection is then stored in an array list. I have another .gsp page that shows student details and within those details it shows which course they selected from the other page. However, when it displays the course it displays like this: "[courseName]", but I would like it to display without the brackets: "courseName".
This is my code for displaying the selection:
<g:if test="${studentDetails?.course}">
<li class="fieldcontain">
<span id="course-label" class="property-label">
<g:message code="student.course.label" default="Course(s)" /></span>
<span class="property-value" aria-labelledby="course-label">
<g:set var="course" value="${studentDetails?.course.courseName}" />
<g:message message="${course}" /></span>
</li>
</g:if>
So far I've tried displaying the variable with g:fieldValue, g:message, and just the variable itself without a tag. All methods display with the brackets. Any suggestions on how to remove the brackets are appreciated. If any other code is needed I can provide it. Thanks.
If your studentDetails?.course.courseName contains a List of courses and your want to display all of them, you need to convert it to a String. But default implementation of List.toString() uses brackets. Your could use .join(',') instead.
Like:
<g:if test="${studentDetails?.course}">
<li class="fieldcontain">
<span id="course-label" class="property-label">
<g:message code="student.course.label" default="Course(s)" /></span>
<span class="property-value" aria-labelledby="course-label">
${studentDetails.course.courseName.join(', ')}
</span>
</li>
</g:if>
Also I suggest to add .encodeAsHTML() if you got this data (course name) from a user, to escape any HTML content inside variables (avoid XSS, etc). Like:
${studentDetails.course.courseName.join(', ').encodeAsHTML()}

changing the class name in nested divs

I have a nested divs as follows, how can I change the class of span in the div whose id is inside-one?
thanks.
my code is as follows:
$("#top span.myclass").removeClass("myclass").addClass("myclass-new");
<div id="top">
<div id="inside-one">
<span id="s1" class="myclass"></span>
</div>
<div id="inside-two">
<span id="s2" class="myclass"></span>
</div>
$('#inside-one').find('span').removeClass('myClass').addClass('myClass-new');
To access from #top without using span ID
$('#top #inside-one span.myclass').toggleClass('myclass-new');
To access from #inside-one without using span ID
$('#inside-one span.myclass').toggleClass('myclass-new');
or simply use the span ID
$('#s1').toggleClass('myclass-new');
Edit: In case if you have many span inside #inside-one and want to access just the first span with .myclass (DEMO)
$('#top #inside-one span.myclass:first-child').toggleClass('myclass-new');
DEMO

Resources