aspose file tools*
The moose likes JSF and the fly likes Dynamic Component in JSF Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » JSF
Bookmark "Dynamic Component in JSF" Watch "Dynamic Component in JSF" New topic
Author

Dynamic Component in JSF

Sandesh Jadhav
Greenhorn

Joined: Nov 01, 2008
Posts: 14
I am new to JSF.I have to add multiple components to the page dynamically on clicking of a command button 'Add component' in the following manner

column1 column2 column3
<HtmlInputText> <Lable> <HtmlInputText>

I also want to bind the same to the arraylist in the backing bean. I am using JSF1.1. I tried it using HtmlPanelGrid, butI couldn't. Can anybody provide me with the simple solution?

Thanks in advance
Darryl Nortje
Ranch Hand

Joined: Jun 11, 2002
Posts: 140
Hi there Sandesh.

Have you had a look at using DataTable. That should work perfectly for what you want to do.

cheers
Darryl
Sandesh Jadhav
Greenhorn

Joined: Nov 01, 2008
Posts: 14
hi Darrry,

Thanks for your suggestion!!!

I have also tried it using the datatable. But still I am not able to achieve what I wanted. May be I was doing it in a wrong way.
My requirement is to add the new text components on clicking of the command button. The page will get refreshed with the new row of components and data from the previous components will be retained back.
Can you provide me with the exact solution or can you show the sample code you have(if any)?

Cheers,
Sandesh
Darryl Nortje
Ranch Hand

Joined: Jun 11, 2002
Posts: 140
Hey Sandesh,

It really sounds like a DataTable will do exactly what you want. Of course I can show you a sample, I've done it a thousand times. But, Not yet. ;-)

Read up a little on DataTable, check out the tutorials. And give it a shot yourself first. I know it's time consuming and difficult but it's the best way to learn. If you're still struggling, then give me a shout again. I'll watch this topic so that it emails me.

Cheers
Darryl
Chris Jebaraj
Ranch Hand

Joined: Sep 19, 2003
Posts: 34
Hi, If you can post the code then we can see whether anything you did wrong. Or otherwise DataTable would do.

One other way to do is, binding the parent HtmlPanelGrid in the UI and do the following
1) When user clicks 'Add' button, invoke an action method in BB
2) In the BB, add whatever components you want and append it with the Parent HtmlPanelGrid
3) Once this action is successful, reload the same page. Now it will have your new components added to the existing list.

If you dont want to reload your page, then AJAX is the best one. You can use AJAX for JSF and try with this.


JebaRaj.<br /> MCP, SCJP 1.5 <br />----------------------------<br /> THOUGH TIMES TEACH TRUST. <br />----------------------------
Sharat Tallam
Greenhorn

Joined: Sep 02, 2008
Posts: 6
I am also having the same requirment as Sandesh, if any simple solution please share...

I tried to call the back bean when click on a button,

<h:form id="form1" styleClass="form">
<hx:commandExButton type="submit" value="Submit" id="button1" styleClass="commandExButton">
<hx:behavior event="onclick" behaviorAction="get" targetAction="group1"></hx:behavior>
</hx:commandExButton>

<h:panelGroup id="group1" styleClass="panelGroup">
<h:inputHidden id="id1" value="#{pc_DynTables.doDisplay}"></h:inputHidden>
<hx:dataTableEx border="0" cellpadding="2" cellspacing="0"
columnClasses="columnClass1" headerClass="headerClass"
footerClass="footerClass" rowClasses="rowClass1, rowClass2, rowClass3, rowClass4"
id="tableEx1" styleClass="dataTableEx" value="#{pc_DynTables.list1}" var="varlist1">
<hx:columnEx id="columnEx1">
<f:facet name="header">
<hutputText id="text1" styleClass="outputText" value="#{varlist1.value1}"></hutputText>
</f:facet>
</hx:columnEx>
<hx:columnEx id="columnEx2">
<f:facet name="header">
<hutputText id="text2" styleClass="outputText" value="#{varlist1.value2}"></hutputText>
</f:facet>
</hx:columnEx>
<hx:columnEx id="columnEx3">
<f:facet name="header">
<hutputText id="text3" styleClass="outputText" value="#{varlist1.value3}"></hutputText>
</f:facet>
</hx:columnEx>
<hx:columnEx id="columnEx4">
<f:facet name="header">
<hutputText id="text4" styleClass="outputText" value="#{varlist1.value4}"></hutputText>
</f:facet>
</hx:columnEx>
</hx:dataTableEx>
</h:panelGroup>
<hx:ajaxRefreshRequest id="ajaxRefreshRequest1" target="group1" params="text5"></hx:ajaxRefreshRequest>

I am using IBM jsf extensions...but the approach would be same ..

On click - calling the ajax behaviour for a panel group component to refresh, in this calling a back bean method to set the list1, but it is not calling the backing bean method ..

Any idea, please reply.. if any suggestions..
Darryl Nortje
Ranch Hand

Joined: Jun 11, 2002
Posts: 140
Hi Sharat,

I suggest starting a new post for this. You're adding a whole lot more than what Sandesh wants to do. Ie Ajax... Amongst other things. I think you'll get help much faster if you do.

Sandesh, did you come right? Let me know your progress.

cheers
Darryl
Sharat Tallam
Greenhorn

Joined: Sep 02, 2008
Posts: 6
Thanks Darryl I will post another you are right my requirement is different from Sandesh..
Sandesh Jadhav
Greenhorn

Joined: Nov 01, 2008
Posts: 14
This is what I have done uptil now and it seems to be working fine.

MyPage.jsp

<td colspan="4"><h:panelGrid binding="#{hostSelection.grid}"/></td>
<h:commandButton id="Add" styleClass="buttonStyle" value="#{label.addButton}" title="#{label.addButton}" actionListener="#{myPage.addNewHost}" />

MyPage.java

private List<HostObj> list = new ArrayList<HostObj>();
private HtmlPanelGrid grid;
HtmlInputText txtIP,txtDir,txtJavaHome,txtOracleHome;
HtmlOutputText txtSec;
HtmlCommandLink removeHost;

public void addNewHost(ActionEvent event){

context = FacesContext.getCurrentInstance();

id = (++integerId).toString();

HostObj hostObj = new HostObj();

txtIP = new HtmlInputText();
txtIP.setStyleClass("INPUT");
txtIP.setId(txtIP.getClientId(context)+id);
txtIP.setValue(hostObj.getIpAddress());

txtDir = new HtmlInputText();
txtDir.setStyleClass("INPUT");
txtDir.setId(txtDir.getClientId(context)+id);
txtDir.setValue(hostObj.getDirPath());

txtSec = new HtmlOutputText();
txtSec.setStyleClass("bodyText");
txtSec.setId(txtSec.getClientId(context)+id);
txtSec.setValue("Secondary");

txtJavaHome = new HtmlInputText();
txtJavaHome.setStyleClass("INPUT");
txtJavaHome.setId(txtJavaHome.getClientId(context)+id);
txtJavaHome.setValue(hostObj.getJavaHome());


txtOracleHome = new HtmlInputText();
txtOracleHome.setStyleClass("INPUT");
txtOracleHome.setId(txtOracleHome.getClientId(context)+id);
txtOracleHome.setValue(hostObj.getOracleHome());

removeHost = new HtmlCommandLink();
removeHost.setValue("remove");
removeHost.setId(removeHost.getClientId(context)+id);

grid.setColumns(6);

grid.getChildren().add(txtIP);
grid.getChildren().add(txtSec);
grid.getChildren().add(txtDir);
grid.getChildren().add(txtJavaHome);
grid.getChildren().add(txtOracleHome);
grid.getChildren().add(removeHost);

context.getViewRoot().setTransient(true);

}

public HtmlPanelGrid getGrid(){
return grid;
}

public void setGrid(HtmlPanelGrid grid){
this.grid = grid;
}

HostObj.java

public class HostObj{

private String ipAddress;
private String dirPath;
private String javaHome;
private String oracleHome;

public String getIpAddress() {
return ipAddress;
}

public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}


public String getDirPath() {
return dirPath;
}

public void setDirPath(String dirPath) {
this.dirPath = dirPath;
}

public String getJavaHome() {
return javaHome;
}

public void setJavaHome(String javaHome) {
this.javaHome = javaHome;
}

public String getOracleHome() {
return oracleHome;
}

public void setOracleHome(String oracleHome) {
this.oracleHome = oracleHome;
}


}

when we call a backing bean method, it adds the new row of components everytime.

Now my requirement is that, I want to add a new commandlink on each row of components and register an actionlistener for it. When we click the command
link, the corresponding row of the components should be removed.

Thanks,
Darryl Nortje
Ranch Hand

Joined: Jun 11, 2002
Posts: 140
Hi there Sandesh.

There is a "simpler" way of doing this, and that is as I suggested in the previous post, to use DataTable.

This is what you do. In your jsp file you declare a dataTable component whose value is some list on your bean. That list on your bean will represent each row in the table. If you want to add a row, you simply add a new item to your list on your bean, and your jsf page will automatically render it properly in the table.

Now to get the remove to work. Again there are more than 1 way to do this. But the way I like to do it, is to bind my dataTable on my jsf page, to a HtmlDataTable component in my bean, with appropriate getters and setters, just like you have bound the panelGrid in your page above, to a HtmlPanelGrid component in your bean.

The remove commandLink or button can call an action method in your bean, and the first thing you want to do is figure out which row was acted on. So you ask the DataTable component in your bean for that info, by calling the DataTable.getRowData method, which I think returns the instance of the object in your list. After that you simply call the List.remove(the object returned by getRowData). Rerender your page, and the element has been removed.

That's the theory. Try it out, and if you want some sample code give me shout again.

Tjeers
Darryl
Darryl Nortje
Ranch Hand

Joined: Jun 11, 2002
Posts: 140
Hi there Sandesh,

Here is a lekker simple example of what I was trying to say above. I hope this helps.

Bean:
=====


JSP PAGE:
=========


I hope this helps.

Tjeers
Darryl
Sandesh Jadhav
Greenhorn

Joined: Nov 01, 2008
Posts: 14
Thanks Darryl. I've solved the issue. Your suggestions really helped me. i was initially doing it in a more complicated manner.

MyPage.java

public class MyPage{

private List<HostObj> list = new ArrayList<HostObj>();
HostObj hostObj = null;
private HtmlDataTable table;

public List<HostObj> getList() {
return list;
}

public void setList(List<HostObj> list) {
this.list = list;
}

public HtmlDataTable getTable(){
return table;
}

public void setTable(HtmlDataTable table){
this.table = table;
}

public void addHost(ActionEvent ae){
hostObj = new HostObj();
hostObj.setIpAddress(hostObj.getIpAddress());
hostObj.setDirPath(hostObj.getDirPath());
hostObj.setJavaHome(hostObj.getJavaHome());
hostObj.setOracleHome(hostObj.getOracleHome());
list.add(hostObj);
}

public void removeHost(){
hostObj =(HostObj)table.getRowData();
list.remove(hostObj);
}

}

MyPage.jsp

<h:dataTable value="#{panelGrid.list}" var="loc" binding="#{panelGrid.table}">
<h:column>
<h:inputText value="#{loc.ipAddress}"/>
</h:column>
<h:column>
<hutputText value="Secondary"/>
</h:column>
<h:column>
<h:inputText value="#{loc.dirPath}"/>
</h:column>
<h:column>
<h:inputText value="#{loc.javaHome}"/>
</h:column>
<h:column>
<h:inputText value="#{loc.oracleHome}"/>
</h:column>
<h:column>
<h:commandButton id="remove" styleClass="buttonStyle" value="Remove" action="#{panelGrid.removeHost}"/>
</h:column>
</h:dataTable>
<h:commandButton id="add" styleClass="buttonStyle" value="Add Component" actionListener="#{panelGrid.addHost}">
</h:commandButton>

And it's working fine!!!
Darryl Nortje
Ranch Hand

Joined: Jun 11, 2002
Posts: 140
Very good Sandesh.

Glad I could help.

Tjeers
Darryl
Devika Narasimhaiah
Greenhorn

Joined: Oct 24, 2008
Posts: 2
Hi,

i want to add the JSF Component dynamically on click of Tree Node, i did it throgh some hard coding and it is working also,

MyTree.xhtml
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:fs="myUri"
template="layout/template.xhtml">

<ui:define name="body">
<h:form id="tree2"> <a4jutputPanel ajaxRendered="true"> <rich:panel id="treePanel"> <f:facet name="header">Charts</f:facet> <rich:tree id="tree" ajaxSubmitSelection="true" switchType="ajax" value="#{SelectionBean.rootNode}" var="node" nodeSelectListener="#{SelectionBean.addNewComponent}" reRender="grid1"> <rich:treeNode iconLeaf="/img/true.png" icon="/img/true.png"> <hutputText value="#{node}"/> </rich:treeNode> </rich:tree> </rich:panel> </a4jutputPanel> </h:form> <h:panelGrid styleclass="panelGrid" columns="3" binding="#{SelectionBean.grid}" id="grid1"> </h:panelGrid>



</ui:define>
</ui:composition>

SelectionBean.java:

public void addNewComponent(final NodeSelectedEvent event) {
HtmlTree tree = (HtmlTree) event.getComponent();
String nodeTitle = (String) tree.getRowData();
TreeNode currentNode = tree.getModelTreeNode(tree.getRowKey());

FacesContext _context=FacesContext.getCurrentInstance();
if(nodeTitle.equals("Calendar"))
{
FacesMessages.instance().add("Chart 1 is Selected");
HtmlCalendar cal=new HtmlCalendar();
cal.setId(cal.getClientId(_context)+1);
grid.getChildren().add(cal);
}

if(nodeTitle.equals("CommandButton")){
HtmlCommandButton text1=new HtmlCommandButton();
text1.setValue("Adding the CommandButton ");
text1.setId(text1.getClientId(_context)+1);
grid.getChildren().add(text1);
}

if(nodeTitle.equals("Color Picker")){
HtmlColorPicker color=new HtmlColorPicker();
color.setId(color.getClientId(_context)+1);
grid.getChildren().add(color);
}

if(nodeTitle.equals("Chart")){

}

}

it is working fine, now i want to delete the component on select.

Can anybody help in this.

Thanks in advance

Regards
Devika.N

 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Dynamic Component in JSF