Criação dinâmica de componente de texto em JSF

Galera,
Meu problema é o seguinte, quero criar um campo de texto (InputText) ou area de texto (InputArea) dinamicamente, por intermédio de um botão.

Quero fazer isso pois cada usuário pode criar um (ou mais) formulário de especificação, e cada formulário pode ter um número diferente de especificações. Isso quer dizer que eu não sei quantos campos eu preciso de antemão. Por isso quero fazer um botão que adicione um campo de texto toda vez que for clicado.

Sou iniciante em JSF, estou usando Myfaces e Tomahawk no Eclipse Europa para J2EE developers no Linux.

Galera, consegui descobrir como faz para criar componentes dinamicamente ou programaticamente, o colega ferryman me ajudou bastante e depois eu encontrei um exemplo na net.

Basicamente vc tem que pegar uma instancia da aplicação do FacesContext (FacesContext.getCurrentInstance().getApplication) pois só a partir do application será capaz de usar o método createComponent (Valeu pela dica Ferryman) .

Exemplo:
fonte : http://mail-archives.apache.org/mod_mbox/myfaces-users/200604.mbox/<443A52A3.70403@wavegroup.it>

Esta é a tag que sua pagina tem que conter, precisa de um binding para chamar outro componente

----- jsf ----------------------------
  <h:panelGroup binding="#{testBean.panel}"/>
 ----- /jsf ---------------------------

Este é o seu bean java

 ----- java ---------------------------
   private String name;
   private int age;
   private UIPanel panel;//esta faltando no código original

   public String getName() {
     return name;
   }

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

   public int getAge() {
     return age;
   }

   public void setAge(int age) {
     this.age = age;
   }

   public UIPanel getPanel() {
     if (panel == null) {
       createPanel();
     }
     return panel;
   }

   public void setPanel(UIPanel panel) {
     this.panel = panel;
   }

   private void createPanel() {
     Application application =
             FacesContext.getCurrentInstance().getApplication();
     // componentType and rendererType taken from HtmlPanelGroupTag
     panel = (UIPanel)
          application.createComponent(HtmlPanelGroup.COMPONENT_TYPE);
     panel.setRendererType("javax.faces.Group");
     panel.setId("gen_panel");

     // componentType and rendererType taken from HtmlOutputLabelTag
     HtmlOutputLabel label = (HtmlOutputLabel)
         application.createComponent(HtmlOutputLabel.COMPONENT_TYPE);
     label.setRendererType("javax.faces.Label");
     label.setId("labelName");
     label.setFor("form:name");
     label.setValue("Name :");
     panel.getChildren().add(label);

     // componentType and rendererType taken from HtmlInputTextTag
     HtmlInputText text = (HtmlInputText)
         application.createComponent(HtmlInputText.COMPONENT_TYPE);
     text.setRendererType("javax.faces.Text");
     text.setId("name");
     ValueBinding vb = application.createValueBinding("#{testBean.name}");
     text.setValueBinding("value", vb);
     panel.getChildren().add(text);

     // componentType, rendererType and escape taken from VerbatimTag
     UIOutput verbatim =
         (UIOutput) application.createComponent("javax.faces.Output");
     verbatim.setRendererType("javax.faces.Text");
     verbatim.getAttributes().put("escape", Boolean.FALSE);
     verbatim.setId("verbatimName");
     verbatim.setValue("<BR>");
     panel.getChildren().add(verbatim);

     label = (HtmlOutputLabel)
         application.createComponent(HtmlOutputLabel.COMPONENT_TYPE);
     label.setRendererType("javax.faces.Label");
     label.setId("labelAge");
     label.setFor("form:age");
     label.setValue("Age :");
     panel.getChildren().add(label);

     text = (HtmlInputText)
         application.createComponent(HtmlInputText.COMPONENT_TYPE);
     text.setRendererType("javax.faces.Text");
     text.setId("age");
     vb = application.createValueBinding("#{testBean.age}");
     text.setValueBinding("value", vb);
     panel.getChildren().add(text);

     verbatim =
         (UIOutput) application.createComponent("javax.faces.Output");
     verbatim.setRendererType("javax.faces.Text");
     verbatim.setId("verbatimAge");
     verbatim.getAttributes().put("escape", Boolean.FALSE);
     verbatim.setValue("<BR>");
     panel.getChildren().add(verbatim);
   }
 ----- /java ---------------------------

A saída gerada pelo código java é similar a essa saída

 ----- jsf ----------------------------
 <h:panelGroup >

   <h:outputLabel for="form:name" value="Name :" />
   <h:inputText id="name" value="#{testBean.name}"/>
   <f:verbatim><br></f:verbatim>

  <h:outputLabel for="form:age" value="Age :" />
  <h:inputText id="age" value="#{testBean.age}"/>
  <f:verbatim><br></f:verbatim>

  </h:panelGroup>
 ----- /jsf ---------------------------

Só lembrando que para criar os componentes e para que estes sejam vistos precisamos de um panelGrid ou um panelGroup.

:twisted: :twisted: :twisted: :twisted:

Puta velho,

<%@ taglib uri=“http://myfaces.apache.org/trinidad” prefix=“tr”%>
<%@ taglib uri=“http://richfaces.org/rich” prefix=“rich”%>

to tentando usar esse componente:
rich:datascroller

só que meu sitema usa o trinidad e o tipo do form é tr:form

dai olha só que fita:

parece que o richfaces tem que achar o formulario da pagina, e ai ele usa esse metodo:

UIForm form= RendererUtils.getInstance().getNestingForm(context, component);

que chama esse outro:

UIComponent parent = component.getParent();
while (parent != null && !(parent instanceof UIForm)) {
parent = parent.getParent();
}

bom acontece que como vcs viram meu form é do tipo: tr:form e nao h:form

logo !(parent instanceof UIForm) allways will evaluate false;

e vai ser true, vai entrar no while e vai procurar outro parent, sou seja nunca vou conseguir fazer o fdp entender que meu form nao é h:form…

cai nesse toopico pq eu vi essa linha:

text.setRendererType(“javax.faces.Text”);

bom,

sei la…vou tentar aqui setar um outro form hardcoded no meu componente e ver oque acontece…mas acho que isso nao vai funcionar…

se alguem ai tiver uma luz no fim do tunel, e souber bastante de trinidad…myfaces, richfaces e puder dar uma luz eu vou ser eternamente grato…

valeu.


public static void throwEnclFormReqExceptionIfNeed(FacesContext context, UIComponent component) throws EnclosingFormRequiredException {
		UIForm form= RendererUtils.getInstance().getNestingForm(context, component);
		//TODO nick -> nick - switchType checking can be harmful here
		String switchType = (String) component.getAttributes().get("switchType");
		boolean isSwitchTypeClient = switchType == null ? false : switchType.equalsIgnoreCase("client") ;
		if (form == null && !isSwitchTypeClient){
			throw new EnclosingFormRequiredException(component.getClass().toString()+" (id=\"" + component.getId() + "\") did not find parent form.");
		}		
	}

public UIForm getNestingForm(FacesContext context, UIComponent component) {
		UIComponent parent = component.getParent();
		while (parent != null && !(parent instanceof UIForm)) {
			parent = parent.getParent();
		}

		UIForm nestingForm = null;
		if (parent != null) {
			// link is nested inside a form
			nestingForm = (UIForm) parent;
		}
		return nestingForm;
	}

full stacktrace:

org.richfaces.component.EnclosingFormRequiredException: class org.richfaces.component.html.HtmlDatascroller (id="j_id_jsp_699352210_3i5") did not find parent form.
	at org.richfaces.component.util.FormUtil.throwEnclFormReqExceptionIfNeed(FormUtil.java:45)
	at org.richfaces.renderkit.html.DatascrollerTemplate.doEncodeEnd(DatascrollerTemplate.java:193)
	at org.richfaces.renderkit.html.DatascrollerTemplate.doEncodeEnd(DatascrollerTemplate.java:673)
	at org.ajax4jsf.renderkit.RendererBase.encodeEnd(RendererBase.java:135)
	at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:829)
	at org.apache.myfaces.trinidad.render.RenderUtils.encodeRecursive(RenderUtils.java:69)
	at org.apache.myfaces.trinidad.render.CoreRenderer.encodeChild(CoreRenderer.java:282)
	at org.apache.myfaces.trinidad.render.CoreRenderer.encodeAllChildren(CoreRenderer.java:304)
	at org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.PanelPartialRootRenderer.renderContent(PanelPartialRootRenderer.java:72)
	at org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.PanelPartialRootRenderer.encodeAll(PanelPartialRootRenderer.java:152)
	at org.apache.myfaces.trinidad.render.CoreRenderer.encodeEnd(CoreRenderer.java:208)
	at org.apache.myfaces.trinidad.component.UIXComponentBase.encodeEnd(UIXComponentBase.java:733)
	at org.apache.myfaces.trinidad.component.UIXComponentBase.__encodeRecursive(UIXComponentBase.java:1271)
	at org.apache.myfaces.trinidad.component.UIXComponentBase.encodeAll(UIXComponentBase.java:753)
	at javax.faces.component.UIComponent.encodeAll(UIComponent.java:890)
	at javax.faces.component.UIComponent.encodeAll(UIComponent.java:890)
	at com.sun.faces.application.ViewHandlerImpl.doRenderView(ViewHandlerImpl.java:247)
	at com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:171)
	at org.jboss.seam.jsf.SeamViewHandler.renderView(SeamViewHandler.java:59)
	at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:108)
	at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:189)
	at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:178)
	at org.apache.myfaces.trinidadinternal.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:174)
	at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:108)
	at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:189)
	at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:106)
	at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:248)
	at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:144)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:245)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:147)
	at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:276)
	at org.ajax4jsf.Filter.doFilter(Filter.java:175)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._invokeDoFilter(TrinidadFilterImpl.java:208)
	at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:165)
	at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:138)
	at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at com.powerlogic.jcompany.controle.filter.PlcMasterFilter.doFilter(PlcMasterFilter.java:206)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:525)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.authenticator.SingleSignOn.invoke(SingleSignOn.java:421)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.authenticator.SingleSignOn.invoke(SingleSignOn.java:421)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Thread.java:595)

Olha, estou um pouco afastado de JSF no momento, mas vamos tentar…

Pelo que eu entendi a sua comparação !(parent instanceof UIForm) nunca vai dar certo por um componente ser trinidad e o outro não ser trinidad (não olhei pra saber de qual taglib vem seu “common”)…

Se esse for o caso, tente:

UIComponent form = null; UIComponent parent = component.getParent(); while (parent != null) { if (parent instanceof UIForm || "org.apache.myfaces.trinidad.Form".equals(parent.getFamily()) ) form = parent; break; } parent = parent.getParent(); }

Dê uma modificada a seu gosto…

a parte importante pra vc é essa:

while (parent != null) {
            if (parent instanceof UIForm || 
                "org.apache.myfaces.trinidad.Form".equals(parent.getFamily())  )

retirado de http://struts.apache.org/1.x/struts-faces/xref/org/apache/struts/faces/renderer/CommandLinkRenderer.html