How to repeat output of text via simple for loop in Facelets without model?
Asked Answered
L

2

25

How to repeat output of some content in JSF using only standard tags (ui:, h: etc) ? In other words - how to do equivalent to PHP code below in JSF ? I immediately wanted to take advantage of ui:repeat, but it needs collection - I have only number.

for ($i = 0; $i < 10; $i++) {
    echo "<div>content</div>";
}
Lead answered 7/11, 2011 at 12:14 Comment(0)
P
46

JSF 2.3+

If you're already on JSF 2.3+ then you can use begin/end attributes of <ui:repeat>.

xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
...
<ui:repeat begin="1" end="10">
    <div>content</div>
</ui:repeat>

JSF 2.2-

If you're not on JSF 2.3 yet, then either use <c:forEach> instead (true, mixing JSTL with JSF is sometimes frowned upon, but this should not harm in your particular case because you seem to want to create the view "statically"; it does not depend on any dynamic variables):

xmlns:c="http://java.sun.com/jsp/jstl/core"
...
<c:forEach begin="1" end="10">
    <div>content</div>
</c:forEach>

Or create an EL function to create a dummy array for <ui:repeat>:

package com.example.util;

public final class Functions {

    private Functions() {
        //
    }

    public static Object[] createArray(int size) {
        return new Object[size];
    }
}

which is registered in /WEB-INF/util.taglib.xml:

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib 
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
    version="2.0">
    <namespace>http://example.com/util/functions</namespace> 
    <function>
        <function-name>createArray</function-name>
        <function-class>com.example.util.Functions</function-class>
        <function-signature>Object[] createArray(int)</function-signature>
    </function>
</facelet-taglib>

and is been used as follows

xmlns:util="http://example.com/util/functions"
...
<ui:repeat value="#{util:createArray(10)}">
    <div>content</div>
</ui:repeat>
Protectorate answered 7/11, 2011 at 13:46 Comment(9)
@jFrenetic: I was pretty certain that this was ever reported/requested in JSF/Facelets issue database, but after looking around for more than 15 minutes, I can't find anything.Protectorate
@Protectorate What do You think about mixing JSTL into JSF web-app? I met with the opinions that this is not a good approach ?Lead
It's fine to mix it, you should only keep in mind that JSTL runs during view build time and JSF runs during view render time. If you intend to use JSTL for a view render time purpose, then it's bad. Or when you intend to use JSTL while there's already a JSF component/attribute for the same purpose, then it's also bad. In this particular case, you can't do it with a JSF component and you don't seem to use it for view render time (otherwise you'd really have had a collection), so it should be fine.Protectorate
See also #3343484Protectorate
Bless you for taking the time to maintain the quality of your posts. =)Affix
The enhancement request by @Protectorate was closed because it's been duplicated by another request: java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1102 Everybody that would like to see ui:repeat improved should follow this link, register with java.net, and vote for this request. It's been over a year since BalusC's original request, much too long to wait!Sphincter
@LS: if you're using OmniFaces, checkout of:createArray() and of:createIntegerArray(): showcase-omnifaces.rhcloud.com/showcase/functions/Arrays.xhtmlProtectorate
Thanks for the suggestion, @BalusC. I'm not using OmniFaces, but I will certainly check it out. I'm getting tired of JSF's poor implementation of very basic features.Sphincter
Wow, Nice. This is exactly what I needed.Environment
L
15

Since it needs a collection, you can make a collection (containing as much elements as the number of time you want to output the divs) in the backing bean:

public class MyBean {
  private List list = new ArrayList<Integer();

  { ... populate the list with numbers, for example ... }

  public List getList() {
     return list;
  }
 ...
}

and then:

<ui:repeat value="#{myBean.list}" var="item">
  <div>content</div>
</ui:repeat>

..which would output as many divs as the size of the list property.

Laudian answered 7/11, 2011 at 13:8 Comment(3)
Yes, but it needs to generate List in class. I thought about something simple as in PHP ;)Lead
THIS is the right answer. ui:repeat is the jsf-safe way to do jstl's c:foreachRoley
Yeah, surely this is the best way to do it.Gillispie

© 2022 - 2024 — McMap. All rights reserved.