Вы правы. Теги типа <ui:repeat>
и <p:repeat>
вызываются во время рендеринга. Нет гарантии, что они будут работать со всеми компонентами, и это сильно зависит от того, как они спроектированы. Родительский компонент должен иметь поддержку динамического рендеринга и поддерживать эти теги - в противном случае вам не повезло.
С учетом сказанного вы можете обойти это, используя JSTL, который будет эффективно создавать вашу ленту во время сборки документа, а не во время рендеринга. Используя ваш пример в качестве основы, это будет реализовано следующим образом (обратите внимание, что в этом примере есть зависимости от Lombok и Apache Commons);
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
<h:head>
<title>Dynamic Ribbon Test</title>
</h:head>
<h:body>
<h:form>
<p:ribbon>
<c:forEach var="tab" items="#{dynRibbonBackingBean.tabs}">
<p:tab binding="#{tab}" />
</c:forEach>
</p:ribbon>
</h:form>
</h:body>
@Data
@Named
@ViewScoped
public class DynRibbonBackingBean implements Serializable {
private List<Tab> tabs;
@PostConstruct
private void init() {
tabs = new ArrayList<>();
for (int i = 0; i < RandomUtils.nextInt(5, 15); i++) {
final Tab t = new Tab();
t.setLoaded(true);
t.setTitle(RandomStringUtils.randomAlphabetic(10));
final RibbonGroup r = new RibbonGroup();
r.setLabel(RandomStringUtils.randomAlphabetic(10));
r.setParent(t);
tabs.add(t);
}
}
}
Здесь мы вместо этого используем тег <c:forEach>
для итерации и построения динамической ленты во время сборки документа. В этом примере я полностью рандомизирую ленту во время @PostConstruct
, поэтому вы можете перезагрузить страницу и посмотреть, как меняются вкладки ленты при каждой загрузке страницы (как в количестве, так и в заголовке).
Вы также можете получить дополнительную информацию по этой теме, обратившись к предыдущему Q / A здесь на сайте;
Когда работает для X, но работает для Y