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>";
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
marioosh
  • 27,328
  • 49
  • 143
  • 192

2 Answers2

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>
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • @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. – BalusC Nov 07 '11 at 14:01
  • @BalusC What do You think about mixing JSTL into JSF web-app? I met with the opinions that this is not a good approach ? – marioosh Nov 07 '11 at 14:30
  • 2
    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. – BalusC Nov 07 '11 at 14:32
  • See also http://stackoverflow.com/questions/3342984/jstl-in-jsf2-facelets-makes-sense/3343681#3343681 – BalusC Nov 07 '11 at 14:55
  • Bless you for taking the time to maintain the quality of your posts. =) – casperOne Jan 03 '12 at 17:55
  • The enhancement request by @BalusC was closed because it's been duplicated by another request: http://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! – Mr. Lance E Sloan Jan 31 '13 at 19:18
  • 1
    @LS: if you're using OmniFaces, checkout `of:createArray()` and `of:createIntegerArray()`: https://showcase-omnifaces.rhcloud.com/showcase/functions/Arrays.xhtml – BalusC Jan 31 '13 at 19:22
  • 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. – Mr. Lance E Sloan Feb 01 '13 at 13:16
  • Wow, Nice. This is exactly what I needed. – Dan Torrey Mar 07 '14 at 16:03
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.

Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147