0

Access the applied composer given a component ID

asked 2009-05-30 01:19:45 +0800

windeyu gravatar image windeyu flag of United States
288 3

Is it possible to access the composer applied on a widget, given the widget's ID?

I created a simplified program below to illustrate my case:
-------------------------------------------------------------
<window id="mywindow" apply="MyComposer">
<button onClick="mylabel.value=mywindow.getComputedData()" />
<label id="mylabel" />
</window>
--------------------------------------------------------------
public class MyComposer extends GenericForwardComposer {
public Object getComputedData() {
return "My computed data...";
}
}
--------------------------------------------------------------
For the MVC reason, I put all controller logic in MyComposer. Inside the Button's onClick event handler, I have a trouble invoking the method defined in MyComposer.

I know that
1) If I move my controller logic to a Window subclass and use it by the "use" attribute on Window, the above code will work. But I don't want to put the non-ui logic in a window ui subclass.
2) We can apply multiple composers to the window component. My code above is not sufficient to identify which composer in the list to invoke.
3) Inside the button's onClick event handler, I can do Events.postEvent() to invoke method in MyComposer. However, I need an immediate returned value to do some more UI logic.

Is possible to access a composer?
Thanks in advance!
windeyu

delete flag offensive retag edit

7 Replies

Sort by ยป oldest newest

answered 2009-06-02 04:59:21 +0800

robbiecheng gravatar image robbiecheng
1144 2
http://robbiecheng.sys-co...

You can follow this tutorial to move your event listener to composer instead of scatter them in the view.

/robbie

link publish delete flag offensive edit

answered 2009-06-02 20:26:12 +0800

windeyu gravatar image windeyu flag of United States
288 3

Hi robbiecheng,

Your suggestion is absolutely right in my simplified case that merely illustrated my question. Here is my real complicated case.

I defined two macro components, say A and B, that each contains windows, trees, buttons, listbox, etc. And both A and B have composers applied to the top-level window. The component A can control the component B. For example, the selection of a drop-down list in marco A can load the view in B. The view in B can be edited by user. The component A has button to save the view of B into the database.

The event handlers for the component A are methods defined on A's composer. The view state of the component B can be obtained from a method on B's composer. When the event handlers on A's composer (such as button click) is invoked, I can't figure out a way to call methods on B's composer.

What's your suggestion?
Thanks again.
-windeyu

link publish delete flag offensive edit

answered 2009-06-04 04:31:26 +0800

robbiecheng gravatar image robbiecheng
1144 2
http://robbiecheng.sys-co...

you can use Events.sendEvent(Component comp, Event event) to post events to B.
and using Path utility to target window component on B.
http://www.zkoss.org/javadoc/3.6.1/zk/org/zkoss/zk/ui/Path.html

/robbie

link publish delete flag offensive edit

answered 2009-06-04 09:14:43 +0800

edudant gravatar image edudant
219 1 1 1
zk.datalite.cz
I access the composer via variable:
public class MyComposer extends GenericForwardComposer {
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        comp.setVariable("ctl", this, true);
    }

    public Object getComputedData() {
        return "My computed data...";
    }
}
<window id="mywindow" apply="MyComposer">
  <button onClick="mylabel.value=ctl.getComputedData()" />
  <label id="mylabel" />
</window>
You can use some custom attribute to set arbitrary name of variable where controller is stored from your zul (get the atribute in doAfterCompose and use it instead of "ctl").
link publish delete flag offensive edit

answered 2010-09-02 01:43:06 +0800

ganzgrosserjunge gravatar image ganzgrosserjunge
39

Hello!
I read robbies suggestion and must say that this will not work in special circumstances!
What if I do not know the component where I should post the message to?
In my opinion a component used as a macro should work on its own so that I can use it without knowing ids of Compononents in its parent. Otherwise a macros does not make sense for me.
If I use macro components with ForwardComposer I would like this macro to send events to its above Composer.
Same in other way. In my opinion the goal should be that I get messages from A and send messages to without knowing anything about ids or something else in the subcomponents.
Is there a solution for this?

link publish delete flag offensive edit

answered 2010-09-07 19:27:44 +0800

henrichen gravatar image henrichen
3869 2
ZK Team

updated 2010-09-07 19:32:23 +0800

>In my opinion a component used as a macro should work on its own so that I can use it without knowing ids of Compononents in its parent. Otherwise a macros does not make sense for me.

Outside of the Macro component, this sounds reasonable.

The question is really on how the one design the macro component encapsulate these "subcomponents". We have not found a better way other than writing a Java class that extends the HTMLMacroComponent and handle the encapsulation. However, since 5.0.4, by default, HTMLMacroComponent will supports auto forward events and wire accessible variables from "subcomponents" to your macro component, so it is much easier to implement such encapsulation than before.

Or maybe you have some better idea?

link publish delete flag offensive edit

answered 2012-05-10 15:26:01 +0800

huubf gravatar image huubf
69 1

you can reach the use class from the the composer (apply) by cast,
so put the composer in the use class if you want to seperate View from Control.

for me the following works:

<window
use="MyComponentWindow "
apply="MyComponent">
<button id="a"/>
</window>
create a composer member in the use class and a setter
public void MyComponentWindow.setComposer(MyComponent composer){this.composer = composer};

do this:

public class MyComposer extends GenericForwardComposer {
public Button a;
MyComponentWindow myComponentWindow;

public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
myComponentWindow=(MyComponentWindow)comp;
myComponentWindow.setComposer(this);
}

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2009-05-30 01:19:45 +0800

Seen: 858 times

Last updated: May 10 '12

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More