What I would like to achieve is a single windowArea that can spawn a window or two depending on the user actions. The idea is to have this as a single point of window creation in the system and therefore to be able to dynamically create and destroy the windows.
I can get this to do what I want to an extent, but I begin to struggle around the closing of the window. The process is not easily synchronized client and server side.
I've created in my main page 'index.jsp':
The backing bean is scoped to session to avoid any data loss issues. In here attached to a commandButton I have a link to the following method to produce a window dynamically.
{
final UIBackbaseWindow window = new UIBackbaseWindow();
window.setTitle("Modeless Window");
window.addActionListener(
new ActionListener() {
public void processAction(ActionEvent event1) throws AbortProcessingException {
System.out.println("Window closed.");
}
}
);
window.setUrl("WindowContents.jsp");
getWindowArea().addChild(window);
}
The above code works great, except for one thing. When I try to close the window it fails to trigger the actionListener. I've tried using customActionListeners and manually coded bindings and these did not trigger either.
The plan was for the actionListener to remove the window from the windowArea and therefore keep the server and client in synch with each other.
I saw a post on the site about using the following code to trigger the event.
<e:handler event="close" type="text/javascript"><![CDATA[bb.bjsf.sync(this,'command');]]></e:handler>
<bjsf:outputText value="Some Content"/>
</bjsf:window>
Reference: http://bdn.backbase.com/node/3846
The problem with this is I cannot see how I can trigger a window to be dynamically created with this work around. The number of windows that will be spawned is not known, therefore I think I need to code this in pure java.
I'm not sure how I can achieve this?
Thanks,
Stuart

Hi Stuart, I was able
24 April, 2008 - 12:10 — SenakaHi Stuart,
I was able trigger the actionListner on a
bjsf:windowon click of the close button in the following way. The window area and associated windows are created dynamically and also the actionListner via the backingBean.Hope this helps,
-Senaka
<bjsf:panel id="container" />
<bjsf:panel>
<bjsf:commandButton value="Create 2 windows dynamically" actionListener="#{myBean.create}"></bjsf:commandButton>
</bjsf:panel>
</bjsf:panelSet>
{
FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
Class[] paramTypes = new Class[] { ActionEvent.class };
MethodBinding actionListener = app.createMethodBinding("#{myBean.closeWindow}", paramTypes);
UIBackbaseComponentBase destComp = (UIBackbaseComponentBase) ComponentUtils.findComponent(context.getViewRoot(), "container");
UIBackbaseWindowArea bbWindowArea = new UIBackbaseWindowArea();
bbWindowArea.setId("bbWindowArea01");
bbWindowArea.setShow(true);
UIBackbaseTaskBar bbTaskBar = new UIBackbaseTaskBar();
bbTaskBar.setId("bbTaskBar");
bbTaskBar.setOrientation("top");
UIBackbaseWindow bbWindow01 = new UIBackbaseWindow();
bbWindow01.setId("bbWindow01");
bbWindow01.setLabel("Backbase Window 01");
bbWindow01.setTop("50px");
bbWindow01.setLeft("50px");
bbWindow01.setActionListener(actionListener);
bbWindow01.setShow(true);
UIBackbaseWindow bbWindow02 = new UIBackbaseWindow();
bbWindow02.setId("bbWindow02");
bbWindow02.setLabel("Backbase Window 02");
bbWindow02.setTop("100px");
bbWindow02.setLeft("100px");
bbWindow02.setActionListener(actionListener);
bbWindow02.setShow(true);
bbWindowArea.addChild(bbWindow01);
bbWindowArea.addChild(bbWindow02);
bbWindowArea.addChild(bbTaskBar);
destComp.addChild(bbWindowArea);
}
public void closeWindow(ActionEvent event)
{
System.out.println("Window "+event.getComponent().getId()+ " closed");
}
Thanks for your reply Senaka
24 April, 2008 - 15:34 — stuartstephenHi Senaka,
I tried your example and this worked better, it's definately a big step forward, but not 100% perfect yet. I took the liberty of modifying your code to get it to work as I plan to and hit a secondary problem.
Incidentally, I had general update issues with the taskbar updating so I removed that for now, we can get onto that at another time.
The good news is, it works well dynamically creating the window object id's with multiple presses of the "create 2 windows dynamically" button. However, when I close a window (it doesn't seem to matter which) it then cannot create new windows anymore.
<bjsf:panel id="container">
<bjsf:windowArea id="bbWindowArea01"/>
</bjsf:panel>
<bjsf:panel>
<bjsf:commandButton value="Create 2 windows dynamically" actionListener="#{WindowBackingBean.create}"></bjsf:commandButton>
</bjsf:panel>
</bjsf:panelSet>
{
FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
Class[] paramTypes = new Class[] { ActionEvent.class };
MethodBinding actionListener = app.createMethodBinding("#{WindowBackingBean.closeWindow}", paramTypes);
// UIBackbaseComponentBase destComp = (UIBackbaseComponentBase) ComponentUtils.findComponent(context.getViewRoot(), "container");
UIBackbaseComponentBase bbWindowArea = (UIBackbaseComponentBase)ComponentUtils.findComponent(context.getViewRoot(), "bbWindowArea01");
/*
UIBackbaseWindowArea bbWindowArea = new UIBackbaseWindowArea();
bbWindowArea.setId("bbWindowArea01");
bbWindowArea.setShow(true);
UIBackbaseTaskBar bbTaskBar = new UIBackbaseTaskBar();
bbTaskBar.setId("bbTaskBar");
bbTaskBar.setOrientation("top");
*/
UIBackbaseWindow bbWindow01 = new UIBackbaseWindow();
// bbWindow01.setId("bbWindow01");
bbWindow01.setLabel("Backbase Window 01");
bbWindow01.setTop("50px");
bbWindow01.setLeft("50px");
bbWindow01.setActionListener(actionListener);
bbWindow01.setShow(true);
UIBackbaseWindow bbWindow02 = new UIBackbaseWindow();
// bbWindow02.setId("bbWindow02");
bbWindow02.setLabel("Backbase Window 02");
bbWindow02.setTop("100px");
bbWindow02.setLeft("100px");
bbWindow02.setActionListener(actionListener);
bbWindow02.setShow(true);
bbWindowArea.addChild(bbWindow01);
bbWindowArea.addChild(bbWindow02);
// bbWindowArea.addChild(bbTaskBar);
// destComp.addChild(bbWindowArea);
}
I thought the answer maybe obvious, so I tried to remove the window component from the windowArea in the following fashion. I figured this might be required to keep the application server and the client in synch with each other.
{
System.out.println("Window "+event.getComponent().getId()+ " closed");
FacesContext context = FacesContext.getCurrentInstance();
UIBackbaseComponentBase bbWindowArea = (UIBackbaseComponentBase) ComponentUtils.findComponent(context.getViewRoot(), "bbWindowArea01");
bbWindowArea.removeChild(event.getComponent());
bbWindowArea.setStructureDirty(true);
}
This caused another error at runtime - instead on the close of the window, not on the opening of a new window after a close. There is obviously something wrong?
For it to be truly dynamic I would like to be able to close and open windows in a user defined order. Due to the nature of our application that we are planning we'd like to use a framework to generically handle this kind of action in a single place - mainly to reduce code maintenance by avoiding repeated code.
Thanks,
Stuart
One other quirk I've noticed
24 April, 2008 - 15:43 — stuartstephenWhen you create two windows, move a window and then create two more windows. The position of the moved windows are forgotten. Is there a way to make the windows remember their position?
Thanks,
Stuart
Adding new windows
6 May, 2008 - 13:56 — AlexanderHi Stuart,
By examining the example from Senaka I found that the problem of adding another set of windows has to do with duplicate id's in the client. Maybe you could try to use some static counter integer instance in your backing bean and use it to create unique id's...
Duplicate windows
6 May, 2008 - 14:30 — stuartstephenHi Alexander,
Thank you for your reply.
I too noticed the id issue and you will see in the code that I placed on the thread that I commented out these hard coded id's. This therefore uses backbase generated id's for each window.
Thanks,
Stuart
Does this solve you
6 May, 2008 - 16:42 — AlexanderDoes this solve your problem..?
Also your post about the positioning of the windows, is it that you would like to set the position of the newly created windows the same as the previous created windows and then the position values of their current state?
Not solved.
6 May, 2008 - 16:52 — stuartstephenHi Alexander,
The problem is not solved.
It is fine having a button that produces unlimited windows, that is working okay. The problem is that when you close a window and then press the button again you get an error.
The positioning problem is you press the open window button, move that window to somewhere else in the window area and then press the open window button again. It moves all windows back to their starting position regardless of where the user placed it.
I think this is all made clear in post http://bdn.backbase.com/node/4622#comment-10195.
Thanks,
Stuart
Hi Stuart, could you give me
6 May, 2008 - 17:35 — AlexanderHi Stuart,
could you give me the error message(s) you get.
Thanks.
See Client Side Errors Below
8 May, 2008 - 10:32 — stuartstephenHi Alexander, I replied to the wrong part of the thread. The answer is seen in the one titled "Client Side Errors".
Thanks,
Stuart
Client Side Errors
7 May, 2008 - 13:03 — stuartstephenSorry for the delay, I spent a bit of time upgrading to 4.2.0 from 4.1.2 to see if that helped. Unfortunately it did not.
I do the following to produce the errors:
1. Press the button to open a window or two.
2. Close one of the open windows using the x at the top right of the window.
3. Click the button to open a new window again and get errors outlined below.
* Execution: Invalid method context, method "setAttribute" was called on a node which has been destroyed.. anonymous()
* GENERIC: Javascript error: "Execution: Invalid method context, method "setAttribute" was called on a node which has been destroyed..". b:windowArea function()
* GENERIC: Javascript error: "GENERIC: Javascript error: "Execution: Invalid method context, method "setAttribute" was called on a node which has been destroyed..".". b:windowArea function()
Thanks,
Stuart
Hi stuartstephen, I've
9 May, 2008 - 16:06 — ionutHi stuartstephen,
I've create an example for you in which you can create multiple windows from one single point, you can close them and keep the positions of the windows after a window was destroyed.
This example is a little tricky because you have to synchronize the position from the server with the position from the client manually. This is needed because when you will create a new window the content of the parent container will be refreshed.
The .jsp page is:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://www.backbase.com/2007/jsf" prefix="bjsf"%>
<html>
<body>
<f:view>
<bjsf:application>
<f:verbatim>
<xi:include href="<%=application.getInitParameter("com.backbase.bjsf.CLIENT_BOOT_DIR")%>/bindings/config.xhtml_btl.chameleon.xml" parse="xml"></xi:include>
<xi:include href="<%=application.getInitParameter("com.backbase.bjsf.CLIENT_BOOT_DIR")%>/bindings/www.backbase.com.2007.jsf.client/server.xml" parse="xml"></xi:include>
<bjsfc:server url="index.jsf" identify="id" loadingMessage="__loadingMsg"></bjsfc:server>
<b:loadingMessage id="__loadingMsg">Loading...</b:loadingMessage>
<d:namespace xmlns:d="http://www.backbase.com/2006/tdl" name="http://www.backbase.com/2007/jsf/client">
<d:behavior name="syncIt">
<d:handler event="dragEnd" type="application/javascript"><![CDATA[
bb.bjsf.sync(this, 'position', 'top', bb.html.getBoxObject(this.viewNode).top, 'left', bb.html.getBoxObject(this.viewNode).left);
]]></d:handler>
<d:handler event="close" type="application/javascript"><![CDATA[
bb.bjsf.sync(this, 'close');
]]></d:handler>
</d:behavior>
</d:namespace>
</f:verbatim>
<bjsf:panelSet rows="50% 50%" fullScreen="true">
<bjsf:panel id="container"/>
<bjsf:panel>
<bjsf:commandButton value="Create a window dynamically" actionListener="#{testBean.create}"></bjsf:commandButton>
</bjsf:panel>
</bjsf:panelSet>
</bjsf:application>
</f:view>
</body>
</html>
and the bean is:
import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.el.MethodBinding;
import javax.faces.event.ActionEvent;
import com.backbase.bjsf.component.UIBBComponentBase;
import com.backbase.bjsf.component.UIBackbaseComponentBase;
import com.backbase.bjsf.component.btl.UIBackbaseWindow;
import com.backbase.bjsf.event.CustomActionEvent;
import com.backbase.bjsf.event.DropEvent;
import com.backbase.bjsf.util.ComponentUtils;
public class TestBean {
public void create(ActionEvent event){
FacesContext context = FacesContext.getCurrentInstance();
UIBackbaseWindow window = new UIBackbaseWindow();
window.setLabel("Backbase Window");
window.setTop("50px");
window.setLeft("50px");
window.setShow(true);
window.setBehavior("bjsfc:syncIt");
Application app = context.getApplication();
Class[] paramTypes = new Class[] { CustomActionEvent.class };
MethodBinding customActionListener = app.createMethodBinding("#{testBean.windowActions}", paramTypes);
window.setCustomActionListener(customActionListener);
UIBackbaseComponentBase destComp = (UIBackbaseComponentBase) ComponentUtils.findComponent(context.getViewRoot(), "container");
destComp.addChild(window);
}
public void windowActions (CustomActionEvent event){
String eventType = event.getAtts().get("event").toString();
if(eventType.equals("position")) {
UIBackbaseWindow win =(UIBackbaseWindow)event.getComponent();
win.setTop((String)event.getAtts().get("top")+"px");
win.setLeft((String)event.getAtts().get("left")+"px");
return;
}
if(eventType.equals("close")) {
UIBackbaseWindow window = (UIBackbaseWindow)event.getComponent();
UIBBComponentBase parent = (UIBBComponentBase)window.getParent();
parent.removeChild(window);
}
}
}
I hope this example will be helpful and if you have any more problems we will help you with pleasure.
Thanks
12 May, 2008 - 12:32 — stuartstephenHi ionut,
Thanks for the reply, that's really helpful.
There is just one thing that I noticed. I saw that you had removed the WindowArea from the picture so I modified the code you provided to make it use that instead of the container.
i.e.
//destComp.addChild(bbWindow01);
UIBackbaseComponentBase bbWindowArea = (UIBackbaseComponentBase) ComponentUtils.findComponent(context.getViewRoot(), "windowArea");
bbWindowArea.addChild(bbWindow01);
<bjsf:windowArea id="windowArea" binding="#{WindowBackingBean.windowArea}"/>
</bjsf:panel>
This led me back to the following errors:
GENERIC: Javascript error: "Execution: Invalid method context, method "setAttribute" was called on a node which has been destroyed..". b:windowArea function()
GENERIC: Javascript error: "GENERIC: Javascript error: "Execution: Invalid method context, method "setAttribute" was called on a node which has been destroyed..".". c:create function()
I did all this because I noticed that without the WindowArea actions such as zIndex for windows are not implemented otherwise. I presume I need to implement some events in a similar way to that you have shown me for the window, but I am not entirely sure how to get this right?
Thanks,
Stuart
Hi
13 May, 2008 - 16:34 — ionutHi Stuartsthphen,
If you want to have a windowArea you have to change the :
with:
<bjsf:windowArea id="container"/>
</bjsf:panel>
But if you want to also have a bjsf:taskbar inside the windowArea you will have a problem. We just found a problem and right now is reported in our bug tracking system and we will take care of this as soon as possible.
Best regards, Ionut
Thanks again
13 May, 2008 - 16:41 — stuartstephenHi ionut,
Thanks again for the reply.
I am confused though, isn't what I did effectively the same? I changed the code to find the id of "windowArea" instead of "container".
Thanks,
Stuart
HI
14 May, 2008 - 14:00 — ionutHi,
You are creating your windowArea like this:
In my example I created like this:
The diference is that you bind your windowArea with a UIBackbaseWindowArea. The problem that you are facing is from the way you initialize your UIBackbaseWindowArea. If you are doing just like in the example that Senaka showed you is not good because the UIBackbaseWindowArea object is created every time when you click the button. Senaka example was made to create two windows only once.
I think, if this is the case, you should declare your UIBackbaseWindowArea object as a object property and initialize it on the constructor, in this way will be initialized only once.
If this is not your case please send us your complete test case.
Best regardes, Ionut