Does anyone know a way to get the index of the element in a ui:repeat facelets tag?
<ui:repeat id="topTenGrd" var="dream" value="#{dreamModifyBean.topDreams}">
<h:outputText class="dream-title uppercase" value="#{dream.number}. #{dream.title}" />
</ui:repeat>
Specify a value for the "varStatus" attribute:
<ui:repeat id="..." var="..." value="..." varStatus="myVarStatus">
You can then access the loop index via EL:
#{myVarStatus.index}
Additionally, the following properties are available to the varStatus:
begin of type Integer
end of type Integer
index of type int
step of type Integer
even of type boolean
odd of type boolean
first of type boolean
last of type boolean
For more details, see:
https://docs.oracle.com/javaee/7/javaserver-faces-2-2/vdldocs-facelets/ui/repeat.html
The answer by Brian is good but I think it could be a bit more descriptive for information.
We create UI:Repeat
<ui:repeat id="repeatOne" var="listofValues" varStatus="myVarStatus"> </ui:repeat>
Using UI Repeat we can access the values from the variable we associated with the list 'listofValues'.
Using varStatus we can create another variable that holds different type of information. For example using #{myVarStatus.index} in our list to create a table we can use this information for our index on our list.
1.
2.
3.
Of course if you specify your array to start at 0 then so will your list unless you add 1 to each. #{myVarStatus.index + 1}
These are also very useful in 2D arrays that need to use 2 UI:Repeat that are nested.
Property ___Getter_________Description
current getCurrent() The item (from the collection) for the current round of iteration
index getIndex() The zero-based index for the current round of iteration
count getCount() The one-based count for the current round of iteration
first isFirst() Flag indicating whether the current round is the first pass through the iteration
last isLast() Flag indicating whether the current round is the last pass through the iteration
begin getBegin() The value of the begin attribute
end getEnd() The value of the end attribute
step getStep() The value of the step attribute
Additional Documentation with links:
Attributes for the UI:Repeat can be found here.
Related
I have an iterator loop for whose children I'm using varStatus for id. When I run the below code, it does not show any value and the id becomes "lkextres_" with no index value appended.
<af:iterator value="#{sessionScope.appBB.resourceList}" var="resourceDef" id="itrResourceList" varStatus="vs">
<af:link id="lkextres_#{vs.index}" useWindow="true" immediate="true" />
</af:iterator>
Please help with how do I get index values to put in id. My purpose is to have different id for each child element so i am using varstatus in af:iterator
i have a script that works with internet explorder (ie) and i need to loop the select fields, that it zelf is no ploblem bu the 4 elements got the same ID (on the same page).
How do i let it loop through the 4 fields?
Can i make them more spesified?
the code i use is the following:
ie.document.getElementByID("DownloadImage").Click
The ie code is the following:
field 1
<a id="DownloadButton" href="javascript:__doPostBack('ctl00$ctl00$MainContent$MainContent$ctl00$declaratiebestandView$RetourInformatieGrid$ctl03$DownloadButton','')">CZ_Specificatie_150005697.pdf</a>
field 2
<a id="DownloadButton" href="javascript:__doPostBack('ctl00$ctl00$MainContent$MainContent$ctl00$declaratiebestandView$RetourInformatieGrid$ctl03$DownloadButton','')">CZ_Specificatie_150005697.pdf</a><input name="ctl00$ctl00$MainContent$MainContent$ctl00$declaratiebestandView$RetourInformatieGrid$ctl03$DownloadImage" class="inlineButton" id="DownloadImage" type="image" src="../images/download.png" text="CZ_Specificatie_150005697.pdf">
then it opens the download screen, and then my code continue's (and works :) )
You can loop them by using querySelectorAll to gather all the elements with an id attribute whose values match what you are after. You can distinguish between them by index. This method will allow you to gather them even though the ids are repeating. However, the HTML you have shared downloads the same document so a loop doesn't seem necessary.
Dim nodeList As Object, i As Long
Set nodeList = ie.document.querySelectorAll("[id=DownloadButton]")
For i = 0 to nodeList.Length-1
nodeList.item(i).Click
Next
That loops all of the matching elements and clicks
By index will be specific but if you familiarize yourself with CSS selectors there are a vast number of possibilities for specifying an element.
The id in HTLM must be unique. If it is not unique it is no valid HTML and should be fixed.
HTML4:
http://www.w3.org/TR/html4/struct/global.html
Section 7.5.2:
id = name [CS]
This attribute assigns a name to an element. This name must be unique in a document.
HTML5:
http://www.w3.org/TR/html5/dom.html#the-id-attribute
The id attribute specifies its element's unique identifier (ID). The
value must be unique amongst all the IDs in the element's home subtree
and must contain at least one character. The value must not contain
any space characters.
I'm on JSF-2.1_29. As far as I can see, the order of manged bean's methodw invokation corresponds to how they are placed in the markup. In my particular case I have:
<h:outputText value="Rows count:"/>
<h:outputText value="#{bonusBean.rowsCount}"/>
<rich:dataTable id="bonusesTable"
var="bonus"
value="#{bonusBean.list}"
render="ds"
rowClasses="tr0, tr1">
<!-- Columns, etc... -->
</rich:dataTable>
ManagedBean itself:
public class BonusBean{
private Integer rowsCount = 0;
//GET, SET
public List<BonusActionDTO> getList(){
List<BonusActionDTO> lst = new ArrayList<BonusActionDTO>();
//Getting the list from a persistance storage
rowsCount = lst.size();
return lst;
}
In that case getRowsCount() is being invoked first which returns 0, so the Rows count: 0 is going to be printed when the page is loaded first, although the table may contain some rows. After invokation of getRowsCount() method, getList() is being invoked, so the actual Rows count is going to printed only after refreshing the page. How can I reorder that order of methods invokation? Is it possible in JSF?
I don't know if you can change the order of the getter invocations. But apart of this, the dependency of the result of a get method on the call of another get method is a bad design. Two getter should return the same results without regard of the order in which they are called.
This question already has answers here:
Why JSF calls getters multiple times
(9 answers)
Closed 6 years ago.
In my ADF project , I have a table component on JSF page whose value attribute is bound to method in Managed bean which returns List type object . I am able to show the data on the table but i can see the method being executed as many as 22 times ! Why the method is being called this many times and does the same thing happens with business components as well when we expose them through Data control? TIA
Edit : JSPX code :
<af:table var="row" rowBandingInterval="1"
autoHeightRows="10"
binding="#{backingBeanScope.backing_ForEachExample.t2}"
id="t1" partialTriggers=":::cb1"
styleClass="AFStretchWidth"
value="#{backingBeanScope.backing_ForEachExample.test2}">
<af:column sortable="false" headerText="col1" id="c3">
<af:outputText value="#{row}" id="ot2"/>
</af:column>
</af:table>
Bean Method is :
public List<String> gettest2(){
/* Unique values are derived */
List<String> tab=new ArrayList<String>();
for(String s:uniqueValues){
System.err.println("? Unique Value is : "+s);
tab.add(s);
}
return tab;
}
when you are using ADF BC, data is displayed from you VO which is exposed in AM through a data control, you can specify VO tuning properties, which determine how many records are fetched from database in one round trip. this is named in batches of. you can specify iterator's range size in sync with how many records you are fetching from database in one go and how many you need to dispay in table at UI. af:table has an attribute called fetchSize, if you set this attribute to some value equal to iterator range size say 20, and VO > Tuning > in batches of = 20, it would query only once. by default, VO in batches of is equal to 1, in that case, if you display a table with autoheightrows = 20, in this case table will query data multiple times from database.
I'm storing value expressions in a JSF component with the f:attribute tag, e.g.:
<h:inputText ...>
<f:attribute name="myId1" value="#{bean.prop1}" />
<f:attribute name="myId2" value="#{bean.prop2}" />
<f:attribute name="myId3" value="#{bean.prop3}" />
</h:inputText>
Is there a way to access all of those value expressions programmatically? (without knowlegde of the names myId1, myId2,...)
Section 9.4.2 of the JSF 2.1 specification says that those values are stored "in the component’s ValueExpression Map".
That's the only occurrence of the term "ValueExpression Map" in the complete spec.
How do I access that map?
In the UIcomponent's Method getValueExpression() of the Jboss/Mojarra implementation the map
getStateHelper().get(UIComponentBase.PropertyKeys.bindings)
is used to obtain a single value expression.
I guess that map is a super set of the "ValueExpression Map"?
Can I be sure that all implementations and all inherited (standard) components use that map to store ValueExpressions?
Thanks.
In theory you should be able to see them all by UIComponent#getAttributes():
Map<String, Object> attributes = component.getAttributes();
for (Map.Entry<String, Object> entry : attributes.entrySet()) {
System.out.printf("name=%s, value=%s%n", entry.getKey(), entry.getValue());
}
However, that doesn't work the way as you'd expect. It only returns static attributes. This does not seem to ever going to be fixed/implemented. See also JSF issue 636. I'd suggest to stick to attribtues with predefinied prefix and an incremental numerical suffix, like as you've presented in your example. That's also what I've always used to pass additional information from the component on to custom validators and converters. You can just collect them as follows:
Map<String, Object> attributes = component.getAttributes();
List<Object> values = new ArrayList<Object>();
for (int i = 1; i < Integer.MAX_VALUE; i++) {
Object value = attributes.get("myId" + i);
if (value == null) break;
values.add(value);
}
System.out.println(values);
An alternative to the answer given by BalusC might be to use nested facets or UIParameter components. Facets can be retrieved as a map using getFacets but you probably need to put an additional UIOutput inside each facet to access its value expression.
Nested UIParameters can be accessed by iterating over the components children and checking for instanceof UIParameter. UIParameters have name and value attributes and so could be easily converted to a map.
I have used parameters in a custom component, but I'm not sure how a standard UIInput like in your example reacts to these.
BalusC is right. UIComponent#getAttributes().get(name) gets values from both places - at first from attributes map and then if not found from "value expression map". To put some value you have to call UIComponent#setValueExpression(name, ValueExpression). If value is literal, it gets stored into the attribute map, otherwise into the "value expression map". Everything is ok then.