Как динамически добавлять и удалять вкладки в компоненте p: tabView - PullRequest
4 голосов
/ 05 сентября 2011

Я пытаюсь добавить PrimeFaces <p:tab> динамически. При добавлении второй вкладки я получаю следующее исключение:

"java.lang.IllegalStateException: идентификатор компонента tab0 уже был найден в представлении".

Как я могу решить это?

Вот код вида:

<h:form prependId="false">
    <p:tabView id="tabview" dynamic="true" cache="false" 
        binding="#{testBean.tabView}" 
        activeIndex="#{testBean.activeTab}" >  
        <h:commandButton value="Close" action="#{testBean.removeTab}"/>
    </p:tabView>  
    <h:commandButton value="Add Tab" action="#{testBean.addTab}"/>
</h:form>

Вот код бина:

public String addTab() {
    String tabId="tab"+id;
    System.out.println("Gen Id: "+tabId);
    tab = new Tab();
    tab.setTitle("Title: "+tabId);
    tab.setId(tabId);

    System.out.println("Tab Id: "+tab.getId());
    tabView.getChildren().add(id,this.tab);
    id++;
    return "tabtest.jsf";
}

public String removeTab() {
    tabView.getChildren().remove(activeTab);
    return "tabtest.jsf";
}

Ответы [ 2 ]

11 голосов
/ 19 апреля 2013

Не создавайте компоненты вручную, если все можно просто сделать в представлении.Эта конструкция потерпит неудачу, если компонент находится в более широкой области, чем область запроса.См. Также, например, Атрибут Binding приводит к дублированию идентификатора компонента, найденного в представлении

Следуйте показательному примеру " TabView with Model ", который позволяет динамически заполнять вкладки через здравый смыслмодель и <p:tabView value="..." var="..."> как у <ui:repeat> / <h:dataTable>.

Например, это представление

<h:form>
    <p:tabView value="#{bean.tabs}" var="tab">  
        <p:tab title="#{tab.title}">
            #{tab.content}
            <p:commandButton value="Close" action="#{bean.remove(tab)}" update="@form" />
        </p:tab>
    </p:tabView>  
    <p:commandButton value="Add Tab" action="#{bean.add}" update="@form" />
</h:form>

с этим контроллером

@ManagedBean
@ViewScoped
public class Bean implements Serializable {

    private List<Tab> tabs;

    @PostConstruct
    public void init() {
        tabs = new ArrayList<>();
    }

    public void add() {
        tabs.add(new Tab("tab" + tabs.size(), "some content"));
    }

    public void remove(Tab tab) {
        tabs.remove(tab);
    }

    public List<Tab> getTabs() {
        return tabs;
    }

}

и с этой моделью

public class Tab {

    private String title;
    private String content;

    public Tab(String title, String content) {
        this.title = title;
        this.content = content;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

}
0 голосов
/ 19 апреля 2013

Это потому, что для новой вкладки создается тот же идентификатор (тот, который вы добавляете). Чтобы избежать этого, добавьте переменную к id как

<p:tabView id="tabview_#{testBean.i}" dynamic="true" cache="false"binding="#{testBean.tabView}" 
        activeIndex="#{testBean.activeTab}" >  
        <h:commandButton value="Close" action="#{testBean.removeTab}"/>
 </p:tabView>  
...