Grails - First Ten Values only in g:each - loops

<g:each in="${checking}" status="i" var="checking2">
<g:if test="${i<10}" >//Break The Loop</g:if>
//Do My Work Here
</g:each>
In above example, if its possible to get only first ten values from 'checking'. Suppose checking returns 100 values, I would like to access only first ten values.
I know that is possible by using max:10 in controller and returning only 10 values in list, but I want as stated above.
PS: I am new to this....

You can use ternary operator.
<g:each in="${list.size() < 10 ? list : list.subList(0, 10)}" var="data" status="idx">
${idx} --- ${data}<br/>
</g:each>

Referring to Groovy JDK API Documentation you can use take() to reduce the List before looping
<g:each in="${checking.take(10)}" status="i" var="checking2">
//Do your Work Here

Try some thing like this
<g:each in="[0..9]" var="index">
<g:set var="item" value="${checking[index]}" />
//do whatever you want with item
</g:each>
In short, iterate over range 0..9 and use index as index to your list.

Here you go:
<g:set var="checkings" value="${checking[0..(Math.min(checking.size()-1, 9))]}" />
<g:each in="${checkings}" status="i" var="checking2">
</g:each>

Related

Using Google Sheet's Filter function, clarification needed

I am trying to filter some information with 2 conditionals (something is true and something else is >0)
Independently things work just fine:
=unique(filter(
indirect($A$1&"!$E$3:E"),
indirect($A$1&"!$C$3:C")=TRUE
))
gives me a list of things that are true, and
=unique(filter(
indirect($A$1&"!$E$3:E"),
indirect($A$1&"!$J$3:J")>0
))
gives me a list of things that are >0.
When i try to combine them, like this
=unique(filter(
indirect($A$1&"!$E$3:E"),
indirect($A$1&"!$C$3:C")=TRUE,
indirect($A$1&"!$J$3:J")>0
))
I get an error No matches are found in FILTER evaluation.
What am i missing please?
PS: It goes without saying that I do indeed have things that are both true and are > 0
for non-english locale it would be:
=unique(filter(
indirect($A$1&"!$E$3:E");
indirect($A$1&"!$C$3:C")=TRUE;
indirect($A$1&"!$J$3:J")>0))

FreeMarker and array how to assign an item to a specific position

I need to modify an array element given the position in FreeMarker.
var arr = [];
arr[0] = "Jani";
arr[1] = "Hege";
arr[2] = "Stale";
arr[3] = "Kai Jim";
arr[4] = "Borge";
is possible to do this in freemarker, you can teach me an example
<#macro cuenta d >
<#assign posicion=0>
<#assign arregloCuenta=[]>
<#list args.array?split(",") as value>
<#assign posicion=posicion+1>
<#if d.properties["bchile:tipodoc"]?exists >
<#if d.properties["bchile:tipodoc"] == value>
<#assign arregloCuenta=["juan"]>
<#assign arregloCuenta= arregloCuenta + ["felipe"]> ${args.array[0]} ${posicion} ${arregloCuenta[1]} </#if> </#if> </#list> </#macro>
From FAQ of FreeMarker:
The FreeMarker Template Language doesn't support the modification of sequences/hashes. It's for displaying already calculated things, not for calculating data. Keep templates simple. But don't give up, you will see some advice and tricks below.
And a little more below:
For example, you want to display a keyword index on some very smart way, whose algorithm need you to create and write some sequence variables. Then you should do something like this (ugly situations has ugly solutions...):
<#assign calculatedResults =
'com.example.foo.SmartKeywordIndexHelper'?new().calculate(keywords)>
<#-- some simple algorithms comes here, like: -->
<ul>
<#list calculatedResults as kw>
<li>${kw.word}
</#list>
</ul>
That is, you move out the complex part of the presentation task from the template into Java code. Note that it doesn't affect the data-model, so the presentation is still kept separated from the other application logic. Of course, the drawback is that for this the template author will need the help of a Java programmer, but for complex algorithms that's probably needed anyway.
Also it said that is better to try to use sequence concatenation and sequence slice than this trick.
For slice and concatenation you can think in something like:
seq[0..pos-1] + ["New element"] + seq[pos+1..]
You can read the complete entry in http://freemarker.org/docs/app_faq.html#faq_modify_seq_and_map

How to format a number in ng:pluralize

How to format a number passed into ng:pluralize directive via attribtute 'count'?
Consider following code:
<ng:pluralize count="5000000" when="{'other': '{} things'}"></pluralize>
the output is:
5000000 things
How can I modify this for output to be:
5,000,000 things // in US locale
5 000 000 things // in Czech locale
I tried using filter 'number', but I think I don't know where to put it. It doesn't work in the object passed to attribute 'when'. I tried these:
... when="{'many': '{{{}|number}} things'}"
... when="{'many': '{}|number things'}"
... when="{'many': '{|number} things'}"
You need to assign the value to a variable
<ng:pluralize ng-init="myCount=5000000" count="myCount" when="{'other': '{{myCount|number}} things'}"></ng:pluralize>
This will format the value to the current locale rules
Demo:
plunker
Expanding on #Liviu T.'s answer, there's no real need to use ng-init to assign the variable. You can do it directly in count.
<ng:pluralize count="myCount=5000000" when="{'other': '{{myCount|number}} things'}"></ng:pluralize>

HowTo break out of a Tapestry loop?

So, i am trying to break out of tapestry loop here.
This is my -more or less- simplified scenario:
<ul>
<t:loop source="firstSource" value="firstValue">
<li>
<t:loop source="firstValue" value="secondValue">
<p>${secondValue}</p>
</t:loop>
<t:loop source="secondSource" value="thirdValue">
<p>${thirdValue}</p>
</t:loop>
</li>
</t:loop>
</ul>
What I do not want to have is:
Tapestry loops through all entries in firstValue - then loops through all entries in secondSource. I do not want to iterate through secondSource inside the loop of fristValue as this would iterate through all entries in secondSource - and I just want to do 1 iteration at a time.
What I want to have is:
Tapestry enters the loop for firstValue and does some printing or whatever, then breaks after the first iteration and jumps into secondSource to do the first iteration . After it has finished it jumps back to firstValue and repeats these steps.
This is what in Java the "break;" would do.
I did not find a clue in the Tapestry documentation on how to do this, nor in their forums.
But it has to be possible in some way. I can not imagine I am the only one trying to do this.
Just put an if statement around the logic, probably using an index variable:
<t:loop source="firstSource" value="firstValue">
<li>
<t:loop source="firstValue" value="secondValue" index="firstValueIndex">
<t:if test="firstCondition">
<p>${secondValue}</p>
</t:if>
</t:loop>
<t:loop source="secondSource" value="thirdValue">
<t:if test="secondCondition">
<p>${thirdValue}</p>
</t:if>
</t:loop>
</li>
</t:loop>
In the Java page:
#Property
private int firstValueIndex;
public boolean getFirstCondition() {
// logic to determine whether to break out
return firstValueIndex == 0;
}
public boolean getSecondCondition() {
// logic
}
My guess is that you have three sources of data and are trying to output three columns, is this right?
Sometimes you have to transform your data a little bit: For example, you might need to do some work to convert one value from each of the three inputs into a single value:
public class Row {
Object col1, col2, col2;
}
In your Java code, you would build up a List of Row objects.
In your template, you iterate over the Row objects, rendering the col1, col2 and col3 properties.
(In Tapestry 5.3 and above, a public field can be treated as a property.)
I've used similar techniques to output a calendar, which can be very tricky to manage using conditionals and the like inside the template.
Remember the role of the Controller in MVC: its job to mediate between the model and the view; sometimes that includes some simple transformations of the model data to fit in with the view.

How to check if element in groovy array/hash/collection/list?

How do I figure out if an array contains an element?
I thought there might be something like [1, 2, 3].includes(1) which would evaluate as true.
Some syntax sugar
1 in [1,2,3]
.contains() is the best method for lists, but for maps you will need to use .containsKey() or .containsValue()
[a:1,b:2,c:3].containsValue(3)
[a:1,b:2,c:3].containsKey('a')
For lists, use contains:
[1,2,3].contains(1) == true
If you really want your includes method on an ArrayList, just add it:
ArrayList.metaClass.includes = { i -> i in delegate }
You can use Membership operator:
def list = ['Grace','Rob','Emmy']
assert ('Emmy' in list)
Membership operator Groovy
IMPORTANT Gotcha for using .contains() on a Collection of Objects, such as Domains. If the Domain declaration contains a EqualsAndHashCode, or some other equals() implementation to determine if those Ojbects are equal, and you've set it like this...
import groovy.transform.EqualsAndHashCode
#EqualsAndHashCode(includes = "settingNameId, value")
then the .contains(myObjectToCompareTo) will evaluate the data in myObjectToCompareTo with the data for each Object instance in the Collection. So, if your equals method isn't up to snuff, as mine was not, you might see unexpected results.
def fruitBag = ["orange","banana","coconut"]
def fruit = fruitBag.collect{item -> item.contains('n')}
I did it like this so it works if someone is looking for it.
You can also use matches with regular expression like this:
boolean bool = List.matches("(?i).*SOME STRING HERE.*")

Resources