I am trying to use h:datatable tag to display values of two-dimensional int array. But cannot make it. Could help me with a solution?
So my backing bean is:
public class MC {
...........
public int[][] getAr() {
return ar;
}
public int getColCount(){
return ar[0].length;
}
}
I can display the array with code in foreach tag referring to the array size:
<h:dataTable value="#{mC.ar}" var="dt">
<c:forEach var="fe" begin="0" end="#{mC.colCount-1}">
<h:column>
<f:facet name="header">X</f:facet>
#{dt[fe]}
</h:column>
</c:forEach>
</h:dataTable>
But nothing is printed if I try to use variable from dataTable:
<h:dataTable value="#{mC.ar}" var="dt">
<c:forEach var="fe" items="#{dt}">
<h:column>
<f:facet name="header">XX</f:facet>
#{fe}
</h:column>
</c:forEach>
</h:dataTable>
Could you help me to make it work? Or perhaps you could suggest some better solution to display an array? Thank you
There is quite common mistake done in assumption that c:forEach is processed in the same time the iteration of dataTable is processed. c:forEach is processed once in build JSF tree, in this phase there is NO "dt" variable defined. h:dataTable defines the "dt" variable in JSF restore/render phases. Use the ui:repeat instead of c:forEach if you need to iterate in this phases.
Related
I'd like to use an "Array" in JSTL that looks like this
<c:set var="hideMe" value="${['A','B','C','D']}" scope="application" />
I also have a global VAR called ${checkPageName} which has the name of the current page I am on in it, so I can check against it, as part of the logic (e.g. <c:if test="${checkPageName != hideMe}"> ... </c:if>)
The logic behind this is that if A, B, C or D exist then I will prevent a specific piece of information from being displayed to the user.
Does anyone know how I loop through a JSTL array?
The logic should then decide that if A, B, C or D DO NOT exist, then we display specific information to the user.
I have tried;
<c:forEach items="${hideMe}">
<c:set var="hide" value="true" />
</c:forEach>
<c:if test="${hide != 'true'}">
<div class="showMe">
<h1>Hello Sweetie</h1>
</div>
</c:if>
Could someone please point me in the right direction?
UPDATE: I have now fixed this myself using <c:forTokens>, see the solution below
So I figured it out in the end;
<c:set var="hideMe" value="false" />
<c:forTokens items="A,B,C,D" delims="," var="excludeDisplay">
<c:if test="${checkPageName == excludeDisplay}">
<c:set var="hideMe" value="true" />
</c:if>
</c:forTokens>
<c:if test="${hideMe == 'false}">
DO SOMETHING
</c:if>
checkPageName is a global variable I am checking against in my code to validate well, page names...
So I set a default VAR called hideMe with a value of false, I then use forTokens to create a VAR called excludeDisplay for values A, B, C or D.
I then check these values against my global variable and if they match overwrite the var hideMe with a value of true, this is then used to trigger the content I want to show. If the VAR is false show the content, if it is true, do nothing.
I hope this helps someone else, and I am happy to elaborate on some of the murkier points if anyone wants any more information...
I am trying something new. I want to pass an arraylist with json objects via the property definition in a custom control. the property I called cols and is of type object.
On an xpage i have calculated the value of the property now as followed:
<xc:this.cols><![CDATA[#{javascript:var cols = [];
cols.push({
"colName" : "Petter",
"colValue" : "Developer"
});
cols.push({
"colName" : "Jesper",
"colValue" : "Administrator"
});
return cols;}]]></xc:this.cols>
Now in my repeater I want to use these objects/values. But I am not sure how?
First I tried outside my repeat control just how to access them in JavaScript e.g.:
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript:var cols = compositeData.cols;
cols[0]["colValue"]}]]></xp:this.value>
</xp:text>
<xp:text escape="true" id="computedField3">
<xp:this.value><![CDATA[#{javascript:var cols = compositeData.cols;
cols[1]["colValue"]}]]></xp:this.value>
</xp:text>
This seems to work because I get the values Developer and Administrator returned.
Now I want to access the json in my repeat control but I get lost here.
Here is how I have set up my repeat control:
<xp:repeat id="repeat1" rows="30" var="colObj" indexVar="idx"
value="#{javascript:compositeData.cols}">
Then I have placed a computed text control within my repeat control and try something similar:
<xp:text escape="true" id="computedField2">
<xp:this.value><![CDATA[#{javascript:colObj[idx]["colValue"]}]]></xp:this.value>
</xp:text>
But then I get an error:
com.ibm.xsp.binding.javascript.JavaScriptValueBinding.getValue(JavaScriptValueBinding.java:132)
Can someone explain what I have done wrong and how I should do it correctly?
Try changing this:
<xp:text escape="true" id="computedField2">
<xp:this.value><![CDATA[#{javascript:colObj[idx]["colValue"]}]]>
</xp:this.value>
</xp:text>
To this:
<xp:text escape="true" id="computedField2">
<xp:this.value><![CDATA[#{javascript:colObj["colValue"]}]]>
</xp:this.value>
</xp:text>
You alreadyb have the colObj so, no need to get the subset. The repeat control deals with the idx so, colObj in the repeat is the same as colObj[n] outside the repeat.
<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>
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.
can someone suggest how possible to interpret <c:set> body?
<c:set var="movieList">One,Two,Three</c:set>
<c:set var="movieList">"One","Two","Three"</c:set>
in the first case movieList is a string and in the second it is an array {"One", "Two", "Three"}
what is movieList in these examples:
<c:set var="movieList">"On"e","Tw"o","Thr"ee"</c:set>
<c:set var="movieList">"On\"e","Tw"o","Thr\"ee"</c:set>
There's no difference in the interpreted Java type of the c:set's body. It are in all cases just String.
Even when you set a non-String type as c:set's body using EL such as
<c:set var="foo">${bean.someInteger}</c:set>
it'll be converted to String anyway by String#valueOf().
Only when you process the variable afterwards, there may be difference, depending on how you processed it. For example,
<c:set var="movieList">One,Two,Three</c:set>
<c:set var="realMovieArray" value="${fn:split(movieList, ',')}" />
will result ${realMovieArray} being a String[] with values of One, Two and Three.
<c:set var="alphabet">A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z</c:set>
<c:forTokens items="${alphabet}" delims="," var="letter">
${letter}
</c:forTokens>