I am new to thymeleaf. I am bit confused now. Please check out the codes below
<th:block th:with="${someVarible=false}">
<th:block th:each="dem : ${demo}">
<th:block th:if="${dem.status==0}">
//Here I need to change the value of someVarible to true
</th:block>
</th:block>
<th:block th:if="${someVariable}">Its true</th:block>
</th:block>
I need to edit the value of someVarible . How can I do it. Thanks in advance.
As Lukas said, it's not possible to change the value of a variable in Thymeleaf, because that only applies to the content within that element. However it is possibe to achieve something very similar using Thymeleaf only.
You can use Collection Selection and the ^[...] syntax to select the first element in your list that matches the criteria status==0. This expression would look like:
${demo.^[status==0]}
If the demo list contains an element with status==0, then that will be returned. Otherwise, it will result in null. This can be used directly in your th:if:
<th:block th:if="${demo.^[status==0]}">Its true</th:block>
Or, if you need to use someVariable for other things too, you can assign it to a variable using th:with (Docs):
<th:block th:with="someVariable=${demo.^[status==0]}">
<th:block th:if="${someVariable}">Its true</th:block>
</th:block>
You can't achieve your desired functionality as you described with Thymeleaf.
th:with does just local variable definition which is only available for evaluation inside that fragment.
<div class="example1" th:with="foo=${bar}">
<!--/* foo is availabile here */-->
<th:block th:text="${foo}" />
</div>
<div class="example2">
<!--/* foo is NOT availabile here! */-->
</div>
And you can't change that variable in template. Thymeleaf is just presentation layer, you're trying to achieve something which has to be done on application layer (Java code).
On application layer (Java code) you could do:
Map<Integer, Boolean> fooMap = new HashMap<Integer, Boolean>();
for(Demo demo : demos) {
if(demo.getStatus() == 0) {
fooMap.put(demo.getId(), true);
} else {
fooMap.put(demo.getId(), false);
}
}
And then on presentation layer (Thymeleaf):
<th:block th:each="demo : ${demos}">
<th:block th:text="${demo.getId()}" />
</th:block>
<th:block th:each="demo : ${demos}">
<th:block th:if="${fooMap.get(demo.getId()) == true}">It's true</th:block>
</th:block>
If you don't want to use HashMap you could use inheritance and extend object Demo.
(Please note that code which I wrote is not tested, so it may need some small fixed, but I hope that I helped you.)
Do you have a form? How do you send data to server?
If your variable of type boolean you can add, e.g., a checkbox for editing :
<th:block th:with="${someVarible=false}">
<th:block th:each="dem : ${demo}">
<th:block th:if="${dem.status==0}">
<label for="someVariableCheck">Edit someVariable</label>
<input id="someVariableCheck" type="checkbox" th:value="${someVariable}"/>
</th:block>
</th:block>
<th:block th:if="${someVariable}">Its true</th:block>
Related
I am trying to add ternary condition to shape which is an icon type shape="success-standard" - in shape="name.active ? 'success-standard' : 'times-circle'" that's where I am trying to add a condition for icon type. and using [shape] directive doesn't work
<clr-dg-row class="man-rcs" *ngFor="let name of visibleNames">
<clr-dg-cell (click)="handleRowClick(name)" class="tac">
<clr-icon size="18" shape="name.active ? 'success-standard' : 'times-circle'">
</clr-icon>
</clr-dg-cell>
</clr-dg-row>
Normally I would do it like this but that's not what I am looking for in this case
<clr-dg-cell class="tac">
<clr-icon size="18" *ngIf="name?.active" shape="success-standard" class="is-solid is-success"></clr-icon>
<clr-icon size="18" *ngIf="!name?.active" shape="times-circle" class="is-solid is-danger"></clr-icon>
</clr-dg-cell>
You need to bind to the shape attribute like this. Icons are our web components, so you have to use this different approach.
[attr.shape]=“name.active ? ‘success-standard’ : ‘times-circle’”
See How can I dynamically change the shape of a clr-icon custom element? For more details.
Try this code below
<clr-icon size="18" shape="{{name.active == true ? 'success-standard' : 'times-circle'}}">
Or
<clr-icon size="18" shape="(name?.active == true ? 'success-standard' : 'times-circle')">
Hope first code will work
I have a basic SpringBoot 2.0.5.RELEASE app. Using Spring Initializer, JPA, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file. I have this template, where I want to disable a select object based on a condition
<form id="menuFormId" class="form-style-9" action="#" th:action="#{/menu/save}" th:object="${menu}" method="post">
<ul>
<li th:each="e : ${#fields.detailedErrors()}" th:class="${e.global}? globalerr : fielderr">
<span th:text="${e.global}? '*' : ${e.fieldName}" ><b>The field name</b></span> : <span th:text="${e.message}" class="red">
<font color="red">The error message</font>
</span>
</li>
</ul>
<ul class="tab_form">
<li>
<select id="selectMenuId" th:field="*{resto}" th:classappend="${menu.id == null} ? disabled='disabled'">
<option value="0">PLEASE SELECT A MENU</option>
</select>
...
But I got this error:
Could not parse as expression: "${menu.id == null} ? disabled='disabled'"
Uhhhh, there are 2 issues:
1.) disabled is a attribute and not a class. Therefore, use the following snippet:
th:disabled="${menu.id == null}"
2.) You can't define a class disabled='disabled'.
The second issue isn't important. There is no need for such a class definition.
There is a base.tl which contains two columns like below:
<li class="column region">
{#partial placeholder = "region" id="column-region" }
{> "templates/partials/column" /}
{/partial}
</li>
<li class="column industry">
{#partial placeholder = "industry" id="column-industry" }
{> "templates/partials/column" /}
{/partial}
</li>
This is the column.tl which contains a input box. I want one of them is readonly and the other is not. So I add readOnly like this.
But I do not know how to parse the boolean readOnly from the base.tl to here.
<div class="column-content">
<input placeholder="{placeholder}"
class="add-preference-input"
type="text" {?readOnly}readonly{/readOnly} />
</div>
Seems like I parse the param like placeholder but it cannot tell it is a boolean. How do I parse a boolean to the partial template and let it be recognized? Is it possible or I have to use javescript to help it.
You're correct that Dust cannot pass booleans directly as params-- they'll just be stringified.
However, the {?exists} tag checks for existence, not truthiness. So you have several options.
Instead of passing true and false, pass "true" and "" (empty string)
{#partial placeholder="region" readonly="" id="column-region"}
Use the {#eq} helper from dustjs-helpers
{#eq key="readonly" value="true" type="boolean"}readonly{/eq}
Put variables in your context that are equal to true and false
{#partial placeholder="region" readonly=FalseContextVar}
Hi I am new to angular I have a requirment as follows.
app.js
$scope.fields = {
"fields": {
"LastName1": "ABC",
"FirstName1": "XYZ",
"LastName2": "123",
"FirstName2": "345",
"LastName3": "PQR",
"FirstName3": "ASD",
}
};
In my html I need to loop over this and display in
index.html
<tr ng-repeat="key in fields">
this doesn't seem to work. Please help.
I want my output as
LastName1 ABC
FirstName1 XYZ
and so on.
Also If user makes any changes to this, I want to be able to push the changes back to fields Json. Please help.
You can use the (key, value) in object syntax.
In your case :
<div ng-repeat="(key1, value1) in fields">
<li ng-repeat="(key2, value2) in value1">{{key2}} : {{value2}}</li>
</div>.
But :
You need to be aware that the JavaScript specification does not define
the order of keys returned for an object. (To mitigate this in Angular
1.3 the ngRepeat directive used to sort the keys alphabetically.)
Version 1.4 removed the alphabetic sorting. We now rely on the order
returned by the browser when running for key in myObj. It seems that
browsers generally follow the strategy of providing keys in the order
in which they were defined, although there are exceptions when keys
are deleted and reinstated. See
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_issues
If this is not desired, the recommended workaround is to convert your
object into an array that is sorted into the order that you prefer
before providing it to ngRepeat. You could do this with a filter such
as toArrayFilter or implement a $watch on the object yourself.
More details : https://docs.angularjs.org/api/ng/directive/ngRepeat
Edit : What if you want to change the object now ?
You can't do :
<div ng-repeat="(key1, value1) in fields">
<h3>{{key1}}</h2>
<li ng-repeat="(key2, value2) in value1">
<input ng-model="value2" /><br />
{{key2}} : {{value2}}
</li>
</div>
Why ? Because ng-model will change value2 in the current scope, and not in your object fields as you don't use dot notation.
For each item/iteration, ng-repeat creates a new scope, which
prototypically inherits from the parent scope, but it also assigns the
item's value to a new property on the new child scope.
More details : https://github.com/angular/angular.js/wiki/Understanding-Scopes
But you can do :
<div ng-repeat="(key1, value1) in fields">
<h3>{{key1}}</h2>
<li ng-repeat="(key2, value2) in value1">
<input ng-model="fields[key1][key2]" /><br />
{{key2}} : {{value2}}
</li>
</div>
Take a look !!!
Try change to:
<tr ng-repeat="(key, value) in fields.fields">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
Here is a working plunker where you can update the model: http://jsfiddle.net/ttgfybk0/1/
Repeat data is in object format like
{
"LastName1": "ABC",
"FirstName1": "XYZ",
"LastName2": "123",
"FirstName2": "345",
"LastName3": "PQR",
"FirstName3": "ASD",
}
use the ng-repeat="(key, value) in expression"
<tr ng-repeat="(key, value) in fields.fields">
<td>{{key}} {{value}}</td>
</tr>
working example ishttp://plnkr.co/edit/Y5lPH1?p=preview
This is a GSP problem/niggle I've faced before in JSP and I'm looking for the cleanest possible solution.
Essentially, I'm using a for loop (<g:each> in GSP) to iterate through a list of items and output a HTML node for each item:
<g:each status="i" var="item" in="items">
<span class="item">${item}</span>
</g:each>
All <span> nodes contain a CSS class of item, but I want the first node to also contain a selected class. Thus, I update the code to:
<g:each status="i" var="item" in="items">
<g:if test="${i == 0}">
<span class="item selected">${item}</span>
</g:if>
<g:else>
<span class="item">${item}</span>
</g:else>
</g:each>
This seems like a complicated approach however as I'm duplicating a lot of code. Another solution is to use a custom tag library and pass the current index into it:
<g:each status="i" var="item" in="items">
<span class="item <g:getItemClass index='${i}' />">${item}</span>
</g:each>
The tag library will return selected when index is equal to 0, otherwise it won't return anything at all. Again, this adds complexity.
Other possible solutions:
Use the index in your CSS class name (very messy)
Set a class name var (). Not better than a custom tag imo.
Use scriptlets (no way)
Any other approaches to this that are clean and simple?
Thanks!
Usually it's just a:
<g:each status="i" var="item" in="items">
<span class="item ${i == 0 ? 'selected' : ''}">${item}</span>
</g:each>