Skip to content

Commit

Permalink
ZK-5792: fullfill doesn't create all components in a forEach
Browse files Browse the repository at this point in the history
  • Loading branch information
jumperchen authored and rebecca0201 committed Sep 25, 2024
1 parent 4d3a590 commit 9319e4d
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 19 deletions.
11 changes: 11 additions & 0 deletions zk/src/main/java/org/zkoss/zk/ui/AbstractComponent.java
Original file line number Diff line number Diff line change
Expand Up @@ -3367,6 +3367,12 @@ public void set(Component o) {

//Cloneable//
public Object clone() {
// remove first.
Collection<Callback> callbacks = new ArrayList<>(getCallback(AFTER_CLONED));
for (Callback callback : new ArrayList<Callback>(callbacks)) {
removeCallback(AFTER_CLONED, callback);
}

final AbstractComponent clone;
try {
clone = (AbstractComponent) super.clone();
Expand Down Expand Up @@ -3396,6 +3402,11 @@ public Object clone() {
if (_auxinf != null)
_auxinf.initClone(clone, clone._auxinf);

// invoke after cloned.
for (Callback callback : new ArrayList<Callback>(callbacks)) {
callback.call(clone);
}

return clone;
}

Expand Down
6 changes: 6 additions & 0 deletions zk/src/main/java/org/zkoss/zk/ui/impl/UiEngineImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
import org.zkoss.zk.ui.sys.UiEngine;
import org.zkoss.zk.ui.sys.Visualizer;
import org.zkoss.zk.ui.sys.WebAppCtrl;
import org.zkoss.zk.ui.util.Callback;
import org.zkoss.zk.ui.util.ComponentCloneListener;
import org.zkoss.zk.ui.util.Composer;
import org.zkoss.zk.ui.util.ComposerExt;
Expand Down Expand Up @@ -2443,6 +2444,10 @@ private FulfillListener(String fulfill, ComponentInfo compInfo, Component comp)
_compInfo = compInfo;
_comp = comp;

// Fix 5792
((ComponentCtrl) _comp).addCallback(ComponentCtrl.AFTER_CLONED,
(Callback) data -> willClone((Component) data));

init();

for (int j = _targets.length; --j >= 0;)
Expand Down Expand Up @@ -2523,6 +2528,7 @@ public Object willClone(Component comp) {
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
// TODO: the original implementation assumed the comp is the _comp, but this listener is added to _targets, not _comp.
clone._comp = comp;
clone.init();
return clone;
Expand Down
17 changes: 4 additions & 13 deletions zk/src/main/java/org/zkoss/zk/ui/impl/UiVisualizer.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* UiVisualizer.java
Purpose:
Description:
History:
Tue Jun 14 10:57:48 2005, Created by tomyeh
Expand Down Expand Up @@ -295,15 +295,6 @@ public void clearSmartUpdate(Component comp) {
_smartUpdated.remove(comp);
}

/** Sets whether to disable the update of the client widget.
* By default, if a component is attached to a page, modifications that
* change the visual representation will be sent to the client to
* ensure the consistency.
*
* @return whether it has been disabled before this invocation, i.e.,
* the previous disable status
* @since 3.6.2
*/
public boolean disableClientUpdate(Component comp, boolean disable) {
if (disable) {
if (_updDisabled == null)
Expand Down Expand Up @@ -1119,15 +1110,15 @@ public void setAbortingReason(AbortingReason reason) {
}

/** Returns the reason to aborting, or null if no aborting at all.
*
*
* @see #setAbortingReason
*/
public AbortingReason getAbortingReason() {
return _aborting;
}

/** Returns whether it is aborting.
*
*
* <p>The execution is aborting if {@link #getAbortingReason} returns
* not null and the returned reason's {@link AbortingReason#isAborting}
* is true.
Expand Down
14 changes: 10 additions & 4 deletions zk/src/main/java/org/zkoss/zk/ui/sys/ComponentCtrl.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* ComponentCtrl.java
Purpose:
Description:
History:
Mon May 30 21:06:56 2005, Created by tomyeh
Expand Down Expand Up @@ -75,6 +75,12 @@ public interface ComponentCtrl {
*/
public static String AFTER_PARENT_CHANGED = "afterParentChanged";

/**
* For after cloned callback, use in {@link #addCallback(String, Callback)}
* @since 10.1.0
*/
public static String AFTER_CLONED = "afterCloned";

/** Sets the component definition.
*
* <p>The component definition affects how a component behaves.
Expand Down Expand Up @@ -234,7 +240,7 @@ public interface ComponentCtrl {
* and the client must send it back even if no listener is registered.
*/
public static final int CE_IMPORTANT = 0x0001;
/** Returned by {@link #getClientEvents} to indicate the event is
/** Returned by {@link #getClientEvents} to indicate the event is
* no deferrable, i.e., the event has to be sent back immediately.
* It is meaningful only used with {@link #CE_IMPORTANT}
*/
Expand All @@ -247,7 +253,7 @@ public interface ComponentCtrl {
* can be ignored by the server when the server receives the same AU
* requests but not processed yet.
* In other words, the server will remove the duplicate AU requests
* if it was queued.
* if it was queued.
*/
public static final int CE_DUPLICATE_IGNORE = 0x2000;
/** Returned by {@link #getClientEvents} to indicate the event
Expand Down
15 changes: 13 additions & 2 deletions zk/src/main/java/org/zkoss/zk/ui/sys/Visualizer.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* Visualizer.java
Purpose:
Description:
History:
Fri Jan 20 23:06:03 2006, Created by tomyeh
Expand Down Expand Up @@ -85,4 +85,15 @@ public interface Visualizer {
* @since 10.0.0
*/
public void enable();

/** Sets whether to disable the update of the client widget.
* By default, if a component is attached to a page, modifications that
* change the visual representation will be sent to the client to
* ensure the consistency.
*
* @return whether it has been disabled before this invocation, i.e.,
* the previous disable status
* @since 10.1.0
*/
public boolean disableClientUpdate(Component comp, boolean disable);
}
1 change: 1 addition & 0 deletions zkdoc/release-note
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ ZK 10.1.0
ZK-5589: a checkmark of a checkbox inside a caption is shifted unexpectedly
ZK-5455: Popup causes error if parent is removed during popup opening animation
ZK-5551: Shadow Component ForEach adds fullfil listeners everytime the syncModel method is called, doesn't clear them if component is removed
ZK-5792: fullfill doesn't create all components in a forEach

* Upgrade Notes
+ Remove Htmls.encodeJavaScript(), Strings.encodeJavaScript(), Strings.escape() with Strings.ESCAPE_JAVASCRIPT, and replace them with OWASP Java Encoder APIs instead.
Expand Down
43 changes: 43 additions & 0 deletions zktest/src/main/webapp/test2/B101-ZK-5792.zul
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>

<!--
B101-ZK-5792.zul
Purpose:
Description:
History:
2024/9/25, Created by jumperchen
Copyright (C) 2024 Potix Corporation. All Rights Reserved.
-->
<zk>
<zscript><![CDATA[
ListModelList model = new ListModelList();
int count = 0;
class MyComp implements org.zkoss.zk.ui.util.Composer {
public void doAfterCompose(Component comp) {
String itemLabel = comp.getParent().getAttribute("item");
Clients.log("executing composer for " + comp + " " + itemLabel);
comp.appendChild(new Label("itemLabel"));
}
}
MyComp myComposer = new MyComp();
]]></zscript>

<button label="add dynamic item" onClick='model.add("item-" + ++count)'/>
<button label="clear model" onClick='model.clear()'/>
<button id="renderAll" label="render all"/>

<div>
<forEach items="${model}">
<div style="border: 1px solid red; height: 20px;"
fulfill="renderAll.onClick">
<custom-attributes item="${each}"/>
<div apply="${myComposer}"/>
</div>
</forEach>
</div>
</zk>
1 change: 1 addition & 0 deletions zktest/src/main/webapp/test2/config.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3143,6 +3143,7 @@ B90-ZK-4431.zul=A,E,Multislider
##manually##B101-ZK-5589.zul=A,E,Iceblue,Theme,Style,checkbox,caption,groupbox
##zats##B101-ZK-5455.zul=A,E,Popup,Data-racing,JS,Error
##zats##B101-ZK-5551.zul=A,E,fulfill,Shadow,ForEach,Model
##zats##B101-ZK-5792.zul=A,E,fulfill,Shadow,ForEach,Model,Differ,EventListener,Clone

##
# Features - 3.0.x version
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* B101_ZK_5792Test.java
Purpose:
Description:
History:
3:30 PM 2024/9/25, Created by jumperchen
Copyright (C) 2024 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.zktest.zats.test2;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

import org.zkoss.test.webdriver.WebDriverTestCase;

/**
* @author jumperchen
*/
public class B101_ZK_5792Test extends WebDriverTestCase {
@Test
public void test() {
connect();
for (int i = 1; i < 6; i++) {
click(jq("@button:eq(0)"));
waitResponse();
assertEquals(1 + i , jq(".z-div").length());
click(jq("@button:eq(2)"));
waitResponse();
assertEquals(i, jq(".z-label:contains(itemLabel)").length());
}
}
}

0 comments on commit 9319e4d

Please sign in to comment.