-
FEATURED COMPONENTS
First time here? Check out the FAQ!
hi there,
i'm in trouble. i've just read documentations and forum-posts, but i've not found any solution for my problem.
i have a composer: MyComposer.java
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
//new UserDB();
UserDB.createPOIs();
//wire variables
Components.wireVariables(comp, this);
//register onXxx event listeners
Events.addEventListeners(comp, this);
//auto forward
Components.addForwards(comp, this);
list.add("Eins");
list.add("Zwei");
comp.setAttribute("test", this, false);
}
public List<String> getList(){
return list;
}
and a zul page: index.zul where i apply my MyComposer.java
in this zul file i want to loop throught the returned list:
<zk forEach="${test.testList}" >
<textbox value="${each}" />
</zk>
the problem is, that this won't work. i found out that in "foreach" there is only EL allowed.
i have to access the variable defined in MyComposer.
I hope someone can help me.
Best Regards
[Edit:] I'm using the latest version of zk
ok i've got it working by using session.setAttribute and bind the component.
my next question is, when i edit the textbox and want to override the current value i have to do that with the onChange event manually or will the "set" methode be called?
the problem is: <textbox id="txt" value="${each}" />
in java i can do the following: public void onChange$txt{} but if more than two textboxes are generated by foreach there is a conflict because all textboxes have the same id. how can i solve this?
<textbox value="Eins"/>
<textbox value="Zwei"/>
if the first textbox changed his value to "One" this new value should also replace "Eins" in the java-List "list" correctly.
First, use the code tags available in this forum editor. Look at the line immediate above the text editor when you're creating a new thread or right above the Post Reply button when replying.
Secondly, the answer to your original post is that forEach is evaluated, using only EL, in the component creation phase of the page's lifecycle. The doAfterCompose() is called later in the rendering phase. So, when your ZUL was evaluated, "testList" had no value.
There's a (apparently) little known interface that GFC implements named ComposeExt that has a doBeforeCompose() method. This is called BEFORE the page is rendered, so it's appropriate to initialize variables there that EL expressions need. Just be aware that when using forEAch, you'll not be able to change the list of components that are generated. EL and forEach are 1 time deals because of them being done during the component creation phase (aka the composer's Compose time in the doBefore/AfterCompose()) unlike those created by databinding.
Third, you're doing things in your doAfterCompose() method that are already done for you. The Components::wireVariables and Components::addForwards are done for you by GFC and its ancestors. Your code should be:
public void doAfterCompose(Component comp) throws Exception { super.doAfterCompose(comp); // stuff done for you here... //new UserDB(); UserDB.createPOIs(); } public void doBeforeCompose(Component comp) throws Exception { super.doBeforeCompose(comp); list.add("Eins"); list.add("Zwei"); comp.setAttribute("test", this, false); }
Hey caclark, thanks for your reply.
i'm knowing the issue with EL.
i'm searching for a solution where i can create textboxes at runtime, where databinding can deal with onChange-Events.
the current solution is i'm creating a listbox with a model="@{win$composer.getList}" then i'm looping the list and create textboxes in listcell. that's working fine, but i don't want to use a listbox or gridbox. i just want the number of textboxes with databinding.
i hope you understand my problem.
Not following you so much...
ok from beginning (i don't know the correct syntax):
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" root="win" ?> <window id="win" apply="myComposer"> <listbox id="box" model="@{win$composer.getAll}"> <listhead> <listheader label="a lot of text" sort="auto" /> </listhead> <listitem self="each..." value="..."> <listcell ><textbox value="@{list.text}" /></listcell </listitem> </listbox> </window>
this snippet works fine, if i'm changing the textbox the databinder binds the new value. he calls list.setText().
the problem is, that i won't use listbox. i want to do it like for-each, but it only works with EL, so when i'm changing the text, the methode list.setText() is not called because of EL.
the result should look like this:
<vlayout> <zk foreach...> <vbox><textbox value="@{list.text}" /></vbox> </zk> </vlayout>
Hook the onChange or onChanging event, as appropriate, and forward it to your controller. Also, look into adding a custom attribute to the textbox and assigning it the value of "each" from your foreach iteration. This will let you retrieve the domain model when the onChange/onChanging event is fired and update the correct value.
Remind me why you don't want to use databinding?
You're only going to be able to use databinding with components that support the model attribute.
From your earlier post:
...but i don't want to use a listbox or gridbox...
Why not?
ftmichael, automatically databinding is not the solution for all things !!!
Try to use an Itemrenderer. In it you can do what you want with your textboxes. And like Cary said, use than the forwarding of the textbox Events.
not tested
public class MyRenderer implements ListitemRenderer { @Override public void render(Listitem item, Object data) throws Exception { final Customer customer = (Customer) data; Listcell lc = new Listcell(customer.getKunNr()); lc.setParent(item); Listcell lc = new Listcell(); Textbox txtbox = new Textbox(); txtbox.setParent(item); ComponentsCtrl.applyForward(txtbox, "onChanging=onChangingMethodInTheController"); item.Value( data) ; }
best
Stephan
Asked: 2011-05-29 10:38:42 +0800
Seen: 1,646 times
Last updated: May 01 '12