# Listening to value change in custom HtmlMacroComponent

ngizk
53 2

Hello. I have created custom component which extends HtmlMacroComponent. It contains four doubleboxes. For value there is simple dto class which contains four variables. Component works correctly and binds correctly on client-side change, however, server-side change to bind value is not reflected in component. I tried adding eventListener for "onChange" event in component but it doesn't fire up when sending notifyChange from vm. I noted however that other events, like onClick, work correctly.

Here is component zul file:

creditbagbox.zul

<zk>
<panel border="none"  closable="false">
<panelchildren>
<grid hflex="1">
<columns>
<column hflex="min" />
<column />
</columns>
<rows>
<row>
<label value="${labels.creditBag.cashable}:"/> <doublebox id="cashableBox" constraint="no negative" format="0.00"/> </row> <row> <label value="${labels.creditBag.playable}:"/>
<doublebox id="playableBox" constraint="no negative" format="0.00"/>
</row>
<row>
<label value="${labels.creditBag.promotional}:"/> <doublebox id="promotionalBox" constraint="no negative" format="0.00"/> </row> <row> <label value="${labels.creditBag.extra}:"/>
<doublebox id="extraBox" constraint="no negative" format="0.00"/>
</row>
</rows>
</grid>
</panelchildren>
</panel>
</zk>


Here is component class (stripped for clarity):

CreditBagBox.java

@ComponentAnnotation({ "value: @ZKBIND(ACCESS=both, SAVE_EVENT=onChange)" })
@Slf4j
public class CreditBagBox extends HtmlMacroComponent {
private static final long serialVersionUID = 1L;

@Getter @Setter
private CreditBag value;

@Wire("#cashableBox")
private Doublebox cashableBox;
@Wire("#playableBox")
private Doublebox playableBox;
@Wire("#promotionalBox")
private Doublebox promotionalBox;
@Wire("#extraBox")
private Doublebox extraBox;

public CreditBagBox() {
setMacroURI("~./creditbagbox.zul");
}

@Override
public void afterCompose() {
super.afterCompose();
}

@Listen("onCreate=doublebox#cashableBox")
public void onCashableCreate(CreateEvent event) {
((Doublebox) event.getTarget()).setValue(value.getCashableCredits() / 100.);
}
[...]

@Listen("onChange=doublebox#cashableBox")
public void onCashableChange(InputEvent event) {
if (event.getValue() == null) {
value.setCashableCredits(0);
} else {
value.setCashableCredits((long) (Double.valueOf(event.getValue()) * 100.));
}
}
[...]
}


<?xml version="1.0" encoding="UTF-8"?>
<language-name>xul/html</language-name>
<depends>zul, zkbind</depends>
<component>
<component-name>creditbag</component-name>
<component-class>terminal.vm.CreditBagBox</component-class>
</component>


Here is how I use this component in zul view:

<creditbag id="amountCreditbagbox" hflex="1" value="@bind(vm.selectedAmount)"/>


My question is: how can I listen for value change in CreditBagBox.java so I can update values in doubleboxes to match new value?

EDIT: Thanks for response, here is fiddle which shows the problem: http://zkfiddle.org/sample/3es4nv4/3-Listening-to-value-change-in-custom-HtmlMacroComponent (please remove space as I cannot post links due to insufficient karma)

As you can see, after clicking "Change values in vm", labels which are bound to amount property change, but my custom component not. My goal is to update doubleboxes inside my component when bound value changes in vm. Binding from component to vm works, which you can see after chaning values in component and clicking Refresh button.

delete retag edit

I have edited my question and added fiddle which shows the problem.

( 2019-04-25 22:39:24 +0800 )edit

( 2019-04-26 12:32:46 +0800 )edit

Sort by » oldest newest most voted

cor3000
4571 2 7

thanks for a running example, I made it working as to what I understood.

http://zkfiddle.org/sample/3es4nv4/4-Listening-to-value-change-in-custom-HtmlMacroComponent

Most changes were in the CreditBagBox ... e.g. I update the doubleboxes when setValue is called, to show the updated values in the UI. During onChange of each doublebox I post an additional event to the macro component to tell the outside world that the user updated the value. The view model can then bind a command on that event to do something else if needed (optional).

I hope this helps.

Thank you. I didn't think about setting these values in setter. It works now.

( 2019-04-26 16:12:35 +0800 )edit

you're welcome

( 2019-04-26 16:31:27 +0800 )edit

cor3000
4571 2 7

thanks for all the detailed description and code. However without running it directly it's hard to guess what's wrong. I also don't fully understand which direction you are planning to wire ... Component -> VM or VM -> Component? A call to notifychange usually doesn't trigger an onChange event in a component ... it's more the opposite way. That an onChange Event from the browser can trigger a @save-binding, which in turn can fire depending @load-bindings.

These kind of problems are difficult and not quickly answered in a forum, unless you can provide a fully runnable example. E.g. on http://zkfiddle.org/.

If this is urgent I'd suggest to ask contact ZK directly for dedicated support.

[hide preview]