[Resolvido] JSF + Primefaces: Tab com conteúdo dinâmico

28 respostas
mews

Pessoal,

Estou tendo dificuldade em inserir um conteúdo dinâmico em uma tab. Já tentei utilizar um include passando a url do xhtml, mas não renderiza.
<p:tabView value="#{tabViewController.tabList}"
				activeIndex="#{tabViewController.activeIndex}" var="tabItem"
				dynamic="true" closeable="true">
				
				<p:ajax event="tabClose" listener="#{tabViewController.onTabClose}"/>
				<p:ajax event="tabChange" listener="#{tabViewController.onTabChange}"/>
				
				<p:tab title="#{tabItem.name}" id="tab" closable="true">
							<p:panel><ui:include src="#{tabItem.url}"/></p:panel> 
								
				</p:tab>
			</p:tabView>
Segue o código do MB:
@SessionScoped
@ManagedBean
public class TabViewController
{
	private List<TabItem> tabList;
	private int activeIndex = 0;

	public TabViewController()
	{
		tabList = new ArrayList<TabItem>();

		tabList.add(new TabItem("tab1", "teste.xhtml", 0));
		tabList.add(new TabItem("tab2", "teste.xhtml", 1));
	}

...
	
	public class TabItem
	{
		private String name;
		private String url;
		private int tabIndex;

		public TabItem(String name, String url, int tabIndex)
		{
			this.setName(name);
			this.setUrl(url);
			this.setTabIndex(tabIndex);
		}

		//getters and setters...
		
	}
}
teste.xhtml
<h:head>

	<title>teste</title>

</h:head>
<h:body style="font-size: 10pt">

	<h:outputText value="conteúdo de teste.xhtml" />
</h:body>

</html>
Então... quando tento acessar o conteúdo do teste.xhtml não aparece nada.

28 Respostas

Hebert_Coelho

na sua pagina que é inserida, deixe apenas o código: <h:outputText value=“conteúdo de teste.xhtml” /> e teste.

mews

não funcionou… e engraçado que ele nem passa pelo método getUrl() do tabItem, somente pelo getName()

Hebert_Coelho

tenta retirar do <p:panel>.

mews

Não deu certo.

Hebert_Coelho

Seus componentes estão dentro de outros componentes? tente coloca-los apenas dentro de um h:head e h:body.

benignoms

O único problema que vejo em seu código é o ui:include. Ele é renderizado em um momento diferente dos componentes do primefaces, por isso não funciona. Você pode criar a tabView dinamicamente utilizando jstl, conforme abaixo:

<p:tabView>
            <c:forEach items="#{tabViewController.tabs}" var="t">
                <p:tab title="#{t.titulo}">
                    <ui:include src="#{t.url}"/>
                </p:tab>
            </c:forEach>
</p:tabView>

espero ter ajudado.

mews

Obrigado benignoms

Resolveu parcialmente o meu problema, pois está mostrando o conteúdo dentro da tab, mas a questão agora é…
Como eu faço para atualizar a tabview quando eu insiro uma nova tab a minha lista no managedbean?

J

Bom dia a todos…
Você conseguiu resolver o problema…
Há algum tempo venho tentando fazer o mesmo, mas não consigo.
Eu queria um menu programável - dinâmico, que, quando eu clicasse em algum item do menu, fosse criada uma nova tab e o conteúdo dela fosse uma página específica, cujo endereço é um atributo da classe menu.
Valeu…

mews

Consegui sim.

menu.xhtml
<h:form>
		<p:accordionPanel value="#{menuController.menus}" var="menu">
			<p:tab title="#{menu.group}">
				<ul>
					<ui:repeat value="#{menu.subMenu}" var="subMenu">
						<p:commandLink ajax="true" oncomplete="updateTabView()">
							<f:setPropertyActionListener target="#{tabViewController.label}"
								value="#{subMenu.label}" />
							<f:setPropertyActionListener target="#{tabViewController.url}"
								value="#{subMenu.url}" />
							<f:setPropertyActionListener target="#{tabViewController.tabID}"
								value="#{subMenu.tabID}" />

							<img id="subMenuIcon"
								src="#{request.contextPath}/img/icons/#{subMenu.iconImg}" />
							<h:outputText value="#{subMenu.label}" />

						</p:commandLink>
						<br />
					</ui:repeat>
				</ul>
				
				<p:remoteCommand name="updateTabView" update=":tabView"></p:remoteCommand>
			</p:tab>
		</p:accordionPanel>
		
	</h:form>
tabView.xhtml
<p:tabView id="tabView"
				activeIndex="#{tabViewController.activeIndex}"
				style="heigth:100%;">
				
				<p:ajax event="tabClose" listener="#{tabViewController.onTabClose}" />
				<p:ajax event="tabChange"
					listener="#{tabViewController.onTabChange}" />

				<c:forEach items="#{tabViewController.tabList}" var="tabItem">
					<p:tab title="#{tabItem.title}" closable="#{tabItem.closeable}" id="#{tabItem.id}">
						<ui:include src="http://#{request.serverName}:#{request.serverPort}#{request.contextPath}/#{tabItem.url}" />
					</p:tab>
				</c:forEach>

			</p:tabView>

O segredo depois de inserido a nova tab a lista contida no tabViewController é fazer o update do componente tabView e isso você pode ver quando faço a chama do remoteCommand no menu.xhtml acima.

<p:remoteCommand name="updateTabView" update=":tabView"></p:remoteCommand>

Não coloquei os controllers porque isso pode ser facilmente compreendido.

J

Mews, valeu pela resposta…
Faz um tempão que eu estou tentando fazer isso… Já tinha até desistido…
Pra falar a verdade eu sou bem fraco em Java.
Vou tentar implementar.

Abração.

J

Mews…
Tô apanhando pra fazer o esquema das tabs…
Você poderia postar os componentes completos?
Valeu…
Abraços…

mews

Vamos fazer ao contrário.
Você coloca o que você já tem e eu te ajudo.

J

Mews… mais uma vez obrigado pela resposta e paciência…
Olha só os códigos que tenho…
São bem simples, mas não tô dando conta.
index.xhtml:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
      
    <f:view contentType="text/html">
        <h:head>
            <f:facet name="first">
                <meta http-equiv="X-UA-Compatible" content="EmulateIE8" />
                <meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
                <title>PrimeFaces - ShowCase</title>
            </f:facet>

            <link type="text/css" rel="stylesheet" href="#{request.contextPath}/resources/css/default.css" />
            <link type="text/css" rel="stylesheet" href="#{request.contextPath}/resources/css/syntaxhighlighter/syntaxhighlighter.css" />

            <style type="text/css">
                .ui-layout-north {
                    z-index:20 !important;
                    overflow:visible !important;;
                }

                .ui-layout-north .ui-layout-unit-content {
                    overflow:visible !important;
                }
            </style>
        </h:head>


        <h:body>

            <p:layout fullPage="true" >

                <p:layoutUnit id="top" position="north" size="50">
                </p:layoutUnit>

                <p:layoutUnit id="bottom" position="south" size="60">
                </p:layoutUnit>

                <p:layoutUnit id="left" position="west" size="300" resizable="true" closable="true" collapsible="true" header="Options" minSize="200">
					<h:form>
						<p:accordionPanel value="#{menuController.menus}" var="menu">
							<p:tab title="#{menu.group}">
								<ul>
									<ui:repeat value="#{menu.subMenu}" var="subMenu">
										<p:commandLink ajax="true" oncomplete="updateTabView()">
											<f:setPropertyActionListener target="#{tabViewController.label}"
												value="#{subMenu.label}" />
											<f:setPropertyActionListener target="#{tabViewController.url}"
												value="#{subMenu.url}" />
											<f:setPropertyActionListener target="#{tabViewController.tabID}"
												value="#{subMenu.tabID}" />
				
											<h:outputText value="#{subMenu.label}" />
				
										</p:commandLink>
										<br />
									</ui:repeat>
								</ul>
								
								<p:remoteCommand name="updateTabView" update=":tabView"></p:remoteCommand>
							</p:tab>
						</p:accordionPanel>
					</h:form>
                </p:layoutUnit>

                <p:layoutUnit id="right" position="east" size="250" header="Gallery" resizable="true" closable="true" collapsible="true" style="text-align:center">
                <h:form>
					 <p:themeSwitcher value="#{themeSwitcherBean.theme}" style="width:150px" effect="fade">
						<f:selectItem itemLabel="Choose Theme" itemValue="" />
						<f:selectItems value="#{themeSwitcherBean.themes}" />
						<p:ajax listener="#{themeSwitcherBean.saveTheme}" />
					 </p:themeSwitcher>
                </h:form>
                </p:layoutUnit>

                <p:layoutUnit id="center" position="center">


					<p:tabView id="tabView"	activeIndex="#{tabViewController.activeIndex}"	style="heigth:100%;">
						<p:ajax event="tabClose" listener="#{tabViewController.onTabClose}" />  
						<p:ajax event="tabChange" listener="#{tabViewController.onTabChange}" />

						<c:forEach items="#{tabViewController.tabList}" var="tabItem">  
							<p:tab title="#{tabItem.title}" id="#{tabItem.id}">  
								<ui:include src="http://#{request.serverName}:#{request.serverPort}#{request.contextPath}/#{tabItem.url}" />  
							</p:tab>  
						</c:forEach> 
					</p:tabView>

                </p:layoutUnit>

            </p:layout>

            <p:dialog header="Basic Dialog" widgetVar="dlg1" modal="true">
                <h:outputText value="Resistance to PrimeFaces is futile!" />
            </p:dialog>

        </h:body>

    </f:view>
</html>

TabViewController.java:

package br.com.sitic.sitic.sistema.controller;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@SuppressWarnings("serial")
@ManagedBean(name="tabViewController")
@ViewScoped
public class TabViewController implements Serializable{
	private List<TabItem> tabList;
	private int activeIndex = 0;

	public TabViewController(){
		tabList = new ArrayList<TabItem>();

		tabList.add(new TabItem("tab1", "teste.xhtml", 0));
		tabList.add(new TabItem("tab2", "teste.xhtml", 1));
	}
	
	public List<TabItem> getTabList() {
		return tabList;
	}

	public void setTabList(List<TabItem> tabList) {
		this.tabList = tabList;
	}

	public int getActiveIndex() {
		return activeIndex;
	}

	public void setActiveIndex(int activeIndex) {
		this.activeIndex = activeIndex;
	}

	public class TabItem implements Serializable{
		private String title;
		private String id;
		private String name;
		private String url;
		private int tabIndex;
		private String label;

		public TabItem(String name, String url, int tabIndex)
		{
			this.setName(name);
			this.setUrl(url);
			this.setTabIndex(tabIndex);
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getUrl() {
			return url;
		}

		public void setUrl(String url) {
			this.url = url;
		}

		public int getTabIndex() {
			return tabIndex;
		}

		public void setTabIndex(int tabIndex) {
			this.tabIndex = tabIndex;
		}

		public String getTitle() {
			return title;
		}

		public void setTitle(String title) {
			this.title = title;
		}

		public String getId() {
			return id;
		}

		public void setId(String id) {
			this.id = id;
		}

		public String getLabel() {
			return label;
		}

		public void setLabel(String label) {
			this.label = label;
		}

		//getters and setters...
		
	}
}
mews

No seu TabViewController você não tem os atributos que estão sendo utilizados no teu Menu.

<f:setPropertyActionListener target="#{tabViewController.label}" value="#{subMenu.label}" /> <f:setPropertyActionListener target="#{tabViewController.url}" value="#{subMenu.url}" /> <f:setPropertyActionListener target="#{tabViewController.tabID}" value="#{subMenu.tabID}" />
Então você pode fazer assim…
Como o clique no link do menu executa algumas tarefas utilizando ajax, você pode sincronizar os eventos.
de acordo como você escreveu o seu menu, o JSF vai setar os valores do label, url e tabID no seu tabViewController.
Significa que depois de ele ter inserido o tabID, você poderá chamar a função addTab() criando um novo objeto tabItem e inserindo ele na tabList.
Por fim, ou seja, no onComplete() do click ele executará o remoteCommand que atualizará a tabView.

Obs: Você precisa que os valores acima dos menus estejam setados.

#{subMenu.label}
#{subMenu.url}
#{subMenu.tabID}
J

Mews...
Mais uma vez peço tua ajuda.
Tô tentando sem sucesso resolver o problema.
A tela tá aparecendo, não dá erro... até o system.out.println que eu coloquei exibe a msg no tomcat.
Mas só exibe a msg de que entrou no
Posto agora todos os códigos que utilizo pra você ver se pode me ajudar.

Menu.java:
package br.com.sitic.sitic.sistema.model;

import java.io.Serializable;
import java.util.List;

@SuppressWarnings("serial")
public class Menu implements Serializable{
	private String group;
	private String label;
	private String url;
	private int tabId;
	private String iconImg;
	private List<Menu> subMenu;
	
	public Menu(String group, String label, String url, int tabId, String iconImg, List<Menu> subMenu){
		this.group = group;
		this.label = label;
		this.url = url;
		this.tabId = tabId;
		this.iconImg = iconImg;
		this.subMenu = subMenu;
	}
	
	public String getGroup() {
		return group;
	}
	public void setGroup(String group) {
		this.group = group;
	}
	public String getLabel() {
		return label;
	}
	public void setLabel(String label) {
		this.label = label;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public int getTabId() {
		return tabId;
	}
	public void setTabId(int tabId) {
		this.tabId = tabId;
	}
	public String getIconImg() {
		return iconImg;
	}
	public void setIconImg(String iconImg) {
		this.iconImg = iconImg;
	}

	public List<Menu> getSubMenu() {
		return subMenu;
	}

	public void setSubMenu(List<Menu> subMenu) {
		this.subMenu = subMenu;
	}
}
MenuController.java:
package br.com.sitic.sitic.sistema.controller;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

import br.com.sitic.sitic.sistema.model.Menu;


@SuppressWarnings("serial")
@ManagedBean(name="menuController")
@SessionScoped
public class MenuController implements Serializable{
	private List<Menu> menus;
	private List<Menu> subMenu;

	public MenuController(){
		int tabId = 0;
		
		menus = new ArrayList<Menu>();
		subMenu = new ArrayList<Menu>();
		subMenu.add(new Menu ("", "Aplicação 1","teste.xhtml",tabId++,"iconImg Sistema-1",null));
		subMenu.add(new Menu ("", "Aplicação 2","teste.xhtml",tabId++,"iconImg Sistema-2",null));
		menus.add(new Menu ("Group Sistema", "Label Sistema","",0,"",subMenu));
	}
	
	public List<Menu> getMenus() {
		return menus;
	}

	public void setMenus(List<Menu> menus) {
		this.menus = menus;
	}
	
}
TabViewController.java:
package br.com.sitic.sitic.sistema.controller;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@SuppressWarnings("serial")
@ManagedBean(name="tabViewController")
@SessionScoped
public class TabViewController implements Serializable{
	private String label;
	private String url;
	private int tabId;
	private List<TabItem> tabList;
	private int activeIndex = 0;

	public TabViewController(){
		tabList = new ArrayList<TabItem>();
		System.out.println("label: "+label+", url: "+url+"tabId: "+tabId);
		if(tabId>0){
			tabList.add(new TabItem(label, url, tabId));
		}
	}
	
	public String getLabel() {
		return label;
	}

	public void setLabel(String label) {
		this.label = label;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public int getTabId() {
		return tabId;
	}

	public void setTabId(int tabId) {
		this.tabId = tabId;
	}

	public List<TabItem> getTabList() {
		return tabList;
	}

	public void setTabList(List<TabItem> tabList) {
		this.tabList = tabList;
	}

	public int getActiveIndex() {
		return activeIndex;
	}

	public void setActiveIndex(int activeIndex) {
		this.activeIndex = activeIndex;
	}

	public class TabItem implements Serializable{
		private String name;
		private String url;
		private int tabIndex;

		public TabItem(String name, String url, int tabIndex)
		{
			this.setName(name);
			this.setUrl(url);
			this.setTabIndex(tabIndex);
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getUrl() {
			return url;
		}

		public void setUrl(String url) {
			this.url = url;
		}

		public int getTabIndex() {
			return tabIndex;
		}

		public void setTabIndex(int tabIndex) {
			this.tabIndex = tabIndex;
		}

	}
}
index.xhtml:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
      
    <f:view contentType="text/html">
        <h:head>
            <f:facet name="first">
                <meta http-equiv="X-UA-Compatible" content="EmulateIE8" />
                <meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
                <title>PrimeFaces - ShowCase</title>
            </f:facet>

            <link type="text/css" rel="stylesheet" href="#{request.contextPath}/resources/css/default.css" />
            <link type="text/css" rel="stylesheet" href="#{request.contextPath}/resources/css/syntaxhighlighter/syntaxhighlighter.css" />

            <style type="text/css">
                .ui-layout-north {
                    z-index:20 !important;
                    overflow:visible !important;;
                }

                .ui-layout-north .ui-layout-unit-content {
                    overflow:visible !important;
                }
            </style>
        </h:head>


        <h:body>

            <p:layout fullPage="true" >

                <p:layoutUnit id="top" position="north" size="50">
                </p:layoutUnit>

                <p:layoutUnit id="bottom" position="south" size="60">
                </p:layoutUnit>

                <p:layoutUnit id="left" position="west" size="300" resizable="true" closable="true" collapsible="true" header="Options" minSize="200">
					<h:form>
						<p:accordionPanel value="#{menuController.menus}" var="menu">
							<p:tab title="#{menu.group}">
								<ul>
									<ui:repeat value="#{menu.subMenu}" var="subMenu">
										<p:commandLink ajax="true" oncomplete="updateTabView()">
											<f:setPropertyActionListener target="#{tabViewController.label}"
												value="#{subMenu.label}" />
											<f:setPropertyActionListener target="#{tabViewController.url}"
												value="#{subMenu.url}" />
											<f:setPropertyActionListener target="#{tabViewController.tabId}"
												value="#{subMenu.tabId}" />
				
											<h:outputText value="#{subMenu.label}" />
											<h:outputText value="#{subMenu.url}" />
											<h:outputText value="#{subMenu.tabId}" />
				
										</p:commandLink>
										<br />
									</ui:repeat>
								</ul>
								
								<p:remoteCommand name="updateTabView" update=":tabView"></p:remoteCommand>
							</p:tab>
						</p:accordionPanel>
					</h:form>
                </p:layoutUnit>

                <p:layoutUnit id="right" position="east" size="250" header="Gallery" resizable="true" closable="true" collapsible="true" style="text-align:center">
                <h:form>
					 <p:themeSwitcher value="#{themeSwitcherBean.theme}" style="width:150px" effect="fade">
						<f:selectItem itemLabel="Choose Theme" itemValue="" />
						<f:selectItems value="#{themeSwitcherBean.themes}" />
						<p:ajax listener="#{themeSwitcherBean.saveTheme}" />
					 </p:themeSwitcher>
                </h:form>
                </p:layoutUnit>

                <p:layoutUnit id="center" position="center">


					<p:tabView id="tabView"	activeIndex="#{tabViewController.activeIndex}"	style="heigth:100%;">
						<p:ajax event="tabClose" listener="#{tabViewController.onTabClose}" />  
						<p:ajax event="tabChange" listener="#{tabViewController.onTabChange}" />

						<c:forEach items="#{tabViewController.tabList}" var="tabItem">   
							<p:tab title="#{tabItem.name}" id="#{tabItem.tabIndex}">   
								<ui:include src="http://#{request.serverName}:#{request.serverPort}#{request.contextPath}/#{tabItem.url}" />   
							</p:tab>   
						</c:forEach>
					</p:tabView>

                </p:layoutUnit>

            </p:layout>

            <p:dialog header="Basic Dialog" widgetVar="dlg1" modal="true"> 
                <h:outputText value="Resistance to PrimeFaces is futile!" />
            </p:dialog>

        </h:body>

    </f:view>
</html>
teste.xhtml:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
 Teste aqui.
</body>
</html>
J

Ooooops…
Fiquei preocupado com os códigos e esqueci de falar do problema.
Eu coloquei um system.out.println pra ver quais os valores que apareceriam a cada vez que fosse chamado o construtor do tabViewController.

Aparece a msg:
label: null, url: nulltabId: 0

Toda vez que a página é chamada pela primeira vez.
Só que como você pode ver, no index.xhtml eu coloquei:
<h:outputText value="#{subMenu.label}" />
<h:outputText value="#{subMenu.url}" />
<h:outputText value="#{subMenu.tabId}" />

O nome do botão aparecem todos os valores, só que, aparentemente, esses valores não são atualizados para os atributos da classe.
Depois não acontece mais nada.
Não aparece mais msg alguma quando clico nos items do menu, nem mesmo é aberta nova aba…
outra coisa que notei foi a falta dos métodos onTabClose e onTabChange no TabViewController… eu não sei o que colocar neles…
qualquer ajuda é bem vinda.

Abraços.

mews

Com relação aos eventos da tab… esses não são necessários.
Eu criei apenas para saber qual tab está selecionada e para remover uma tab da lista quando o usuário fechar a tab.

faz as seguintes alterações:

TabViewController

Altera o teu construtor:

public TabViewController() { tabList = new ArrayList<TabItem>(); }
Cria o método addTab() e coloca dentro dele o seguinte código

this.tabList.add(new TabItem(this.label, this.url, tabIndex));

Quando o JSF chamar o método setTabId() dentro dele você pode chamar o addTab().
Não é a forma mais linda de se fazer, mas é uma forma de sincronizar os eventos para dar conta desse cenário.

Além disso, coloca breakpoint nos teus getters e setters para ver se estão executando corretamente.

J
Eu coloquei nos get e setters

Estão funcionando corretamente.

Estava tentando adicionar os itens por meio de um actionEvent

Olha :

public void adicionarTabItem(ActionEvent actionEvent){

System.out.println(adicionarTabItem…”);

System.out.println("label: “+label+”, url: "+url+"tabId: "+tabId);

tabList.add(new TabItem(label, url, tabId));

}

O resultado foi:

Quando eu clico em um botão/link, aparecem as mensagens:

adicionarTabItem

label: menuxx, url: urlxxx: tabId: 1.

Mas a mensagem só aparece uma vez… posso clicar quantas vezes eu quizer, não acontece mais nada.
Só quando eu tento atualizar a página CTRL F5, aí dá um erro doido:

16/02/2012 16:18:47 org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() for servlet [Faces Servlet] in context with path [/sitic] threw exception [0] with root cause
java.lang.IllegalArgumentException: 0
	at javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:542)
bla bla bla....

Acho que isso tá acontecendo porque a classe é SessionScoped, e eu deveria chaamr o ActionEvent em uma classe ViewScoped, correto?
Esse caminho que eu tô tentando seguir vai dar certo ou é melhor fazer como você tá falando?
Mais uma vez obrigado pela ajuda.

mews

Você pode fazer dessa forma, porém os eventos são assíncronos e por isso que quando você manda adicionar a tab os valores estão null.
O outro problema é que você precisa colocar um id único para cada tab adicionada. Para isso adicione um novo atributo no TabItem e depois passe para o xhtml.

J

Vou fazer como você falou…

Só que a tab não é criada.
Quando eu entro na página pela primeira vez aparece a msg:

Construtor…
label: null, url: nulltabId: 0

Quando eu clico no link/botão aparece:

Setando label: Aplicação 2
addTab…
label: Aplicação 2, url: teste.xhtmltabId: 1

Mas nada acontece, nenhuma tab é criada.
Aí quando eu clico em outro ou no mesmo link, nada acontece…
Quando eu dou um refresh (CTRL F5) na página, aparece:

GRAVE: Servlet.service() for servlet [Faces Servlet] in context with path [/sitic] threw exception [1] with root cause
java.lang.IllegalArgumentException: 1
	at javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:542)
	at javax.faces.component.UIComponentBase.setId(UIComponentBase.java:363)
bla bla bla...

Olha como ficou meu TabViewController:

package br.com.sitic.sitic.sistema.controller;

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name="tabViewController")
@SessionScoped
public class TabViewController {
	private String label;
	private String url;
	private int tabId;
	private List<TabItem> tabList;
	private int activeIndex = 0;

	public TabViewController(){
		tabList = new ArrayList<TabItem>();
		System.out.println("Construtor...");
		System.out.println("label: "+label+", url: "+url+"tabId: "+tabId);
	}
	
	public void addTab(){
		System.out.println("addTab...");
		System.out.println("label: "+label+", url: "+url+"tabId: "+tabId);
		this.tabList.add(new TabItem(this.label, this.url, this.tabId));
	}
	
	public String getLabel() {
		return label;
	}

	public void setLabel(String label) {
		System.out.println("Setando label: "+label);
		this.label = label;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public int getTabId() {
		return tabId;
	}

	public void setTabId(int tabId) {
		this.tabId = tabId;
		addTab();
	}

	public List<TabItem> getTabList() {
		return tabList;
	}

	public void setTabList(List<TabItem> tabList) {
		this.tabList = tabList;
	}

	public int getActiveIndex() {
		return activeIndex;
	}

	public void setActiveIndex(int activeIndex) {
		this.activeIndex = activeIndex;
	}

	public class TabItem {
		private String name;
		private String url;
		private int tabIndex;

		public TabItem(String name, String url, int tabIndex)
		{
			this.setName(name);
			this.setUrl(url);
			this.setTabIndex(tabIndex);
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getUrl() {
			return url;
		}

		public void setUrl(String url) {
			this.url = url;
		}

		public int getTabIndex() {
			return tabIndex;
		}

		public void setTabIndex(int tabIndex) {
			this.tabIndex = tabIndex;
		}

	}
}

E o index.xhtml:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
      
    <f:view contentType="text/html">
        <h:head>
            <f:facet name="first">
                <meta http-equiv="X-UA-Compatible" content="EmulateIE8" />
                <meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
                <title>PrimeFaces - ShowCase</title>
            </f:facet>

            <link type="text/css" rel="stylesheet" href="#{request.contextPath}/resources/css/default.css" />
            <link type="text/css" rel="stylesheet" href="#{request.contextPath}/resources/css/syntaxhighlighter/syntaxhighlighter.css" />

            <style type="text/css">
                .ui-layout-north {
                    z-index:20 !important;
                    overflow:visible !important;;
                }

                .ui-layout-north .ui-layout-unit-content {
                    overflow:visible !important;
                }
            </style>
        </h:head>


        <h:body>

            <p:layout fullPage="true" >

                <p:layoutUnit id="top" position="north" size="50">
                </p:layoutUnit>

                <p:layoutUnit id="bottom" position="south" size="60">
                </p:layoutUnit>

                <p:layoutUnit id="left" position="west" size="300" resizable="true" closable="true" collapsible="true" header="Options" minSize="200">
					<h:form>
						<p:accordionPanel value="#{menuController.menus}" var="menu">
							<p:tab title="#{menu.group}">
								<ul>
									<ui:repeat value="#{menu.subMenu}" var="subMenu">
										<p:commandLink ajax="true" oncomplete="updateTabView()">
											<f:setPropertyActionListener target="#{tabViewController.label}"
												value="#{subMenu.label}" />
											<f:setPropertyActionListener target="#{tabViewController.url}"
												value="#{subMenu.url}" />
											<f:setPropertyActionListener target="#{tabViewController.tabId}"
												value="#{subMenu.tabId}" />
											
											<h:outputText value="#{subMenu.label}" />
											<h:outputText value="#{subMenu.url}" />
											<h:outputText value="#{subMenu.tabId}" />
											
										</p:commandLink>
										<br />
									</ui:repeat>
								</ul>
								
								<p:remoteCommand name="updateTabView" update=":tabView"></p:remoteCommand>
							</p:tab>
						</p:accordionPanel>
					</h:form>
                </p:layoutUnit>

                <p:layoutUnit id="right" position="east" size="250" header="Gallery" resizable="true" closable="true" collapsible="true" style="text-align:center">
                <h:form>
					 <p:themeSwitcher value="#{themeSwitcherBean.theme}" style="width:150px" effect="fade">
						<f:selectItem itemLabel="Choose Theme" itemValue="" />
						<f:selectItems value="#{themeSwitcherBean.themes}" />
						<p:ajax listener="#{themeSwitcherBean.saveTheme}" />
					 </p:themeSwitcher>
                </h:form>
                </p:layoutUnit>

                <p:layoutUnit id="center" position="center">


					<p:tabView id="tabView"	activeIndex="#{tabViewController.activeIndex}"	style="heigth:100%;">
						<p:ajax event="tabClose" listener="#{tabViewController.onTabClose}" />  
						<p:ajax event="tabChange" listener="#{tabViewController.onTabChange}" />

						<c:forEach items="#{tabViewController.tabList}" var="tabItem">   
							<p:tab title="#{tabItem.name}" id="#{tabItem.tabIndex}">   
								<ui:include src="http://#{request.serverName}:#{request.serverPort}#{request.contextPath}/#{tabItem.url}" />   
							</p:tab>   
						</c:forEach>
					</p:tabView>

                </p:layoutUnit>

            </p:layout>

            <p:dialog header="Basic Dialog" widgetVar="dlg1" modal="true"> 
                <h:outputText value="Resistance to PrimeFaces is futile!" />
            </p:dialog>

			<h:form>
			<p:remoteCommand name="rcAdicionarTabItem" actionListener="#{tabTeste.adicionarTabItem}" update=":tabView"></p:remoteCommand>
			</h:form>
        </h:body>

    </f:view>
</html>

Abraços e obrigado.

GRAVE: Servlet.service() for servlet [Faces Servlet] in context with path [/sitic] threw exception [1] with root cause
java.lang.IllegalArgumentException: 1
	at javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:542)
	at javax.faces.component.UIComponentBase.setId(UIComponentBase.java:363)
J

Vou fazer como você falou…

Só que a tab não é criada.
Quando eu entro na página pela primeira vez aparece a msg:

Construtor…
label: null, url: nulltabId: 0

Quando eu clico no link/botão aparece:

Setando label: Aplicação 2
addTab…
label: Aplicação 2, url: teste.xhtmltabId: 1

Mas nada acontece, nenhuma tab é criada.
Aí quando eu clico em outro ou no mesmo link, nada acontece…
Quando eu dou um refresh (CTRL F5) na página, aparece:

GRAVE: Servlet.service() for servlet [Faces Servlet] in context with path [/sitic] threw exception [1] with root cause
java.lang.IllegalArgumentException: 1
	at javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:542)
	at javax.faces.component.UIComponentBase.setId(UIComponentBase.java:363)
bla bla bla...

Olha como ficou meu TabViewController:

package br.com.sitic.sitic.sistema.controller;

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name="tabViewController")
@SessionScoped
public class TabViewController {
	private String label;
	private String url;
	private int tabId;
	private List<TabItem> tabList;
	private int activeIndex = 0;

	public TabViewController(){
		tabList = new ArrayList<TabItem>();
		System.out.println("Construtor...");
		System.out.println("label: "+label+", url: "+url+"tabId: "+tabId);
	}
	
	public void addTab(){
		System.out.println("addTab...");
		System.out.println("label: "+label+", url: "+url+"tabId: "+tabId);
		this.tabList.add(new TabItem(this.label, this.url, this.tabId));
	}
	
	public String getLabel() {
		return label;
	}

	public void setLabel(String label) {
		System.out.println("Setando label: "+label);
		this.label = label;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public int getTabId() {
		return tabId;
	}

	public void setTabId(int tabId) {
		this.tabId = tabId;
		addTab();
	}

	public List<TabItem> getTabList() {
		return tabList;
	}

	public void setTabList(List<TabItem> tabList) {
		this.tabList = tabList;
	}

	public int getActiveIndex() {
		return activeIndex;
	}

	public void setActiveIndex(int activeIndex) {
		this.activeIndex = activeIndex;
	}

	public class TabItem {
		private String name;
		private String url;
		private int tabIndex;

		public TabItem(String name, String url, int tabIndex)
		{
			this.setName(name);
			this.setUrl(url);
			this.setTabIndex(tabIndex);
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getUrl() {
			return url;
		}

		public void setUrl(String url) {
			this.url = url;
		}

		public int getTabIndex() {
			return tabIndex;
		}

		public void setTabIndex(int tabIndex) {
			this.tabIndex = tabIndex;
		}

	}
}

E o index.xhtml:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
      
    <f:view contentType="text/html">
        <h:head>
            <f:facet name="first">
                <meta http-equiv="X-UA-Compatible" content="EmulateIE8" />
                <meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
                <title>PrimeFaces - ShowCase</title>
            </f:facet>

            <link type="text/css" rel="stylesheet" href="#{request.contextPath}/resources/css/default.css" />
            <link type="text/css" rel="stylesheet" href="#{request.contextPath}/resources/css/syntaxhighlighter/syntaxhighlighter.css" />

            <style type="text/css">
                .ui-layout-north {
                    z-index:20 !important;
                    overflow:visible !important;;
                }

                .ui-layout-north .ui-layout-unit-content {
                    overflow:visible !important;
                }
            </style>
        </h:head>


        <h:body>

            <p:layout fullPage="true" >

                <p:layoutUnit id="top" position="north" size="50">
                </p:layoutUnit>

                <p:layoutUnit id="bottom" position="south" size="60">
                </p:layoutUnit>

                <p:layoutUnit id="left" position="west" size="300" resizable="true" closable="true" collapsible="true" header="Options" minSize="200">
					<h:form>
						<p:accordionPanel value="#{menuController.menus}" var="menu">
							<p:tab title="#{menu.group}">
								<ul>
									<ui:repeat value="#{menu.subMenu}" var="subMenu">
										<p:commandLink ajax="true" oncomplete="updateTabView()">
											<f:setPropertyActionListener target="#{tabViewController.label}"
												value="#{subMenu.label}" />
											<f:setPropertyActionListener target="#{tabViewController.url}"
												value="#{subMenu.url}" />
											<f:setPropertyActionListener target="#{tabViewController.tabId}"
												value="#{subMenu.tabId}" />
											
											<h:outputText value="#{subMenu.label}" />
											<h:outputText value="#{subMenu.url}" />
											<h:outputText value="#{subMenu.tabId}" />
											
										</p:commandLink>
										<br />
									</ui:repeat>
								</ul>
								
								<p:remoteCommand name="updateTabView" update=":tabView"></p:remoteCommand>
							</p:tab>
						</p:accordionPanel>
					</h:form>
                </p:layoutUnit>

                <p:layoutUnit id="right" position="east" size="250" header="Gallery" resizable="true" closable="true" collapsible="true" style="text-align:center">
                <h:form>
					 <p:themeSwitcher value="#{themeSwitcherBean.theme}" style="width:150px" effect="fade">
						<f:selectItem itemLabel="Choose Theme" itemValue="" />
						<f:selectItems value="#{themeSwitcherBean.themes}" />
						<p:ajax listener="#{themeSwitcherBean.saveTheme}" />
					 </p:themeSwitcher>
                </h:form>
                </p:layoutUnit>

                <p:layoutUnit id="center" position="center">


					<p:tabView id="tabView"	activeIndex="#{tabViewController.activeIndex}"	style="heigth:100%;">
						<p:ajax event="tabClose" listener="#{tabViewController.onTabClose}" />  
						<p:ajax event="tabChange" listener="#{tabViewController.onTabChange}" />

						<c:forEach items="#{tabViewController.tabList}" var="tabItem">   
							<p:tab title="#{tabItem.name}" id="#{tabItem.tabIndex}">   
								<ui:include src="http://#{request.serverName}:#{request.serverPort}#{request.contextPath}/#{tabItem.url}" />   
							</p:tab>   
						</c:forEach>
					</p:tabView>

                </p:layoutUnit>

            </p:layout>

            <p:dialog header="Basic Dialog" widgetVar="dlg1" modal="true"> 
                <h:outputText value="Resistance to PrimeFaces is futile!" />
            </p:dialog>

			<h:form>
			<p:remoteCommand name="rcAdicionarTabItem" actionListener="#{tabTeste.adicionarTabItem}" update=":tabView"></p:remoteCommand>
			</h:form>
        </h:body>

    </f:view>
</html>

Abraços e obrigado.

GRAVE: Servlet.service() for servlet [Faces Servlet] in context with path [/sitic] threw exception [1] with root cause
java.lang.IllegalArgumentException: 1
	at javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:542)
	at javax.faces.component.UIComponentBase.setId(UIComponentBase.java:363)
J

Rapaiz…
O problema tá na hora que eu coloco o id pra tab que será criada, aqui:

<p:tabView id="tabView"	activeIndex="#{tabViewController.activeIndex}"	style="heigth:100%;">
						<p:ajax event="tabClose" listener="#{tabViewController.onTabClose}" />  
						<p:ajax event="tabChange" listener="#{tabViewController.onTabChange}" />

						<c:forEach items="#{tabViewController.tabList}" var="tabItem">   
							<p:tab title="#{tabItem.name}" [b]id="#{tabItem.tabIndex}"[/b]>   
								<ui:include src="http://#{request.serverName}:#{request.serverPort}#{request.contextPath}/#{tabItem.url}" />   
							</p:tab>   
						</c:forEach>
					</p:tabView>

Na criação do menu eu defini que cada aplicação terá o seu nro de tab fixo, mas acho que isso não dá certo né?
Quem tem que definir a tab como um contador é o TabViewController?
Valeu…
Abraço…

J

Consegui…
Pelo menos + ou -…
Tô trabalhando no onTabClose…
Pra removê-la quando ela for fechada…

Abração e obrigado pela ajuda.

mews

Que bom que deu certo.
Agora é só lapidar para chegar ao modelo ideal para você.

Valeu

fabiozanardi

Olá, estou seguindo o exemplo abaixo e tendo esse mesmo problema abaixo também na hora de gerar uma aba nova clicando no addTab:

GRAVE: Servlet.service() for servlet [Faces Servlet] in context with path [/sitic] threw exception [1] with root cause  
java.lang.IllegalArgumentException: 1  
    at javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:542)  
    at javax.faces.component.UIComponentBase.setId(UIComponentBase.java:363)

como fizeram para corrigir?

grato

fabiozanardi

Consegue resolver os problemas de uma forma diferente, com esse foreach ele volta todas as abas ao estado inicial quando abrimos outra aba, assim se temos campos de formulários que alteramos ou um resultado de pesquisa, eles estavam todos voltando ao estado inicial de quando a aba foi aberta.

valeu galera.

L

Estou querendo desenvolver um produto utilizando JSF 2.2 e Primefaces 4.0 com essa idéia do jlferreira, vocês conseguiram alguma coisa, se sim por favor postem aí a solução encontrada.

R

Como você resolveu a questão dos ID’s? Poderia postar o código aqui ?

Criado 23 de janeiro de 2012
Ultima resposta 21 de mai. de 2014
Respostas 28
Participantes 7