0

Custom component that extends Textbox does not fire onChange event

asked 2017-04-03 16:55:17 +0800

trapongx gravatar image trapongx
32 3

updated 2017-04-04 04:05:38 +0800

I tried to create a very simple custom text by extending existing Textbox component. The component displayed correctly with bound value. The problem is, when I make change to the input, the browser does not fire onChange event to the server-side. Is this a bug or am I doing something wrong?

This is my code in lang-addon.xml

<language-addon>
  <addon-name>myzkcomp</addon-name>
    <version>
      <version-class>net.bitreplay.Version</version-class>
      <version-uid>1.0-SNAPSHOT</version-uid>
      <zk-version>8.0.2.2</zk-version>
  </version>

  <language-name>xul/html</language-name>

  <component>
      <component-name>jpatextbox</component-name>
      <component-class>net.bitreplay.JpaTextbox</component-class>
      <extends>textbox</extends>
  </component>
</language-addon>

in index.zul

<zk>
  <window title="Hello World!!" border="normal" width="300px"
      apply="org.zkoss.bind.BindComposer"
      viewModel="@id('vm') @init('test.ctrl.MyVm')">
      <jpatextbox value="@bind(vm.name)"/>
  </window>
</zk>

in MyVm.java

package test.ctrl;

public class MyVm {
    private String name = "Hooray";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

in Version.java

package net.bitreplay;

public class Version {
  public static final String UID = "1.0-SNAPSHOT";
}

I tried the same thing with Intbox and Combobox. They give me the same problem.

This show the version of ZK I'm using via Gradle build

 compile("org.zkoss.zk:zkbind:8.0.2.2")
 compile("org.zkoss.zk:zul:8.0.2.2")
 compile("org.zkoss.zk:zuti:8.0.2.2-Eval")
 compile("org.zkoss.zk:zkmax:8.0.2.2-Eval")
 compile("org.zkoss.zk:zkex:8.0.2.2-Eval")
 compile("org.zkoss.zk:zkplus:8.0.2.2")
 compile("org.zkoss.zk:zhtml:8.0.2.2")
 compile("org.zkoss.zk:zkspring-core:3.2.0")

---- Update ----

Hi chillworld. The system require me to wait for 2 days before I can add answer to my own question so I edit the question to put it.

Sorry, I thought I provided the code for the component already. This is it

package net.bitreplay;

import org.zkoss.zul.Textbox;

public class JpaTextbox extends Textbox {
}

binding_annotation_for_a_custom_component (I have not enough karma to post the link, please google it). I tried adding this annotation to the JpaTextbox class.

@ComponentAnnotation("value:@ZKBIND(ACCESS=both, SAVE_EVENT=onChange)")

And it works for me. However, it would be very helpful if anyone could kindly explain me why the built-in component "org.zkoss.zul.Textbox" work well without having to have the binding definition in such form of annotation nor in lang.xml (I've looked in the definition of parent classes of Textbox also). Is it just because JpaTextbox is custom so it need different ceremony?

delete flag offensive retag edit

Comments

and your actual code of the component?

chillworld ( 2017-04-03 18:30:57 +0800 )edit

3 Answers

Sort by ยป oldest newest most voted
2

answered 2017-04-05 02:28:17 +0800

MDuchemin gravatar image MDuchemin
2560 1 6
ZK Team

updated 2017-04-05 02:29:35 +0800

Try adding a <depends> element in your lang-addon.xml Since these bindings are defined in zkbind, you need to make sure that you wait until zkbind has modified the default textbox.

https://www.zkoss.org/wiki/ZK%20Client-side%20Reference/Language%20Definition/depends

<depends>zkbind</depends>
link publish delete flag offensive edit

Comments

Thanks a lot, MDuchemin. It works for me and seems to be the direct hit to my problem.

trapongx ( 2017-04-05 08:51:36 +0800 )edit

Cool, then this makes sense. You were actually extending the default textbox before it received the binding instructions from parsing zkbind.jar.

MDuchemin ( 2017-04-05 11:05:38 +0800 )edit

Don't forget to mark the answer as solution to give the hint for other people ;)

MDuchemin ( 2017-04-05 11:06:07 +0800 )edit

Thank you for reminding me. I've marked it as solution.

trapongx ( 2017-04-06 09:23:57 +0800 )edit
0

answered 2017-04-04 05:06:30 +0800

MDuchemin gravatar image MDuchemin
2560 1 6
ZK Team

Hi trapongx,

Tested building with maven (shouldn't matter how packages are obtained), running on jetty. No issue for me. I can get the onChange event from the custom textbox without declaring Component annotations.

How do you check if the onChange event has fired? From client side, most reliable way is to look at the network tab and check for zkau requests holding data like:

dtid:z_pvz
cmd_0:onChange
uuid_0:n5CQ1
data_0:{"value":"Hoorayaa","start":8}

To answer the question of why does default ZK works directly: those binding instructions are packaged in zkbind.jar/src/archive/metainfo/zk/lang-addon.xml . If you open it from github or your package, and you will find the textbox bindings here:

<component>
        <component-name>textbox</component-name>
        <extends>textbox</extends>
        <annotation>
            <annotation-name>ZKBIND</annotation-name>
            <property-name>value</property-name>
            <attribute>
                <attribute-name>ACCESS</attribute-name>
                <attribute-value>both</attribute-value>
            </attribute>
            <attribute>
                <attribute-name>SAVE_EVENT</attribute-name>
                <attribute-value>onChange</attribute-value>
            </attribute>
            <attribute>
                <attribute-name>LOAD_REPLACEMENT</attribute-name>
                <attribute-value>rawValue</attribute-value>
            </attribute>
            <attribute>
                <attribute-name>LOAD_TYPE</attribute-name>
                <attribute-value>java.lang.String</attribute-value>
            </attribute>
        </annotation>
        <annotation>
            <annotation-name>ZKBIND</annotation-name>
            <property-name>errorMessage</property-name>
            <attribute>
                <attribute-name>ACCESS</attribute-name>
                <attribute-value>load</attribute-value>
            </attribute>
            <attribute>
                <attribute-name>CONVERTER</attribute-name>
                <attribute-value>org.zkoss.bind.converter.sys.ErrorMessageConverter</attribute-value>
            </attribute>
        </annotation>
    </component>

PS: you should be able to reply now ;)

link publish delete flag offensive edit

Comments

also, onChange only fires after blur, unless you use instant mode

MDuchemin ( 2017-04-04 05:09:04 +0800 )edit
0

answered 2017-04-04 17:40:35 +0800

trapongx gravatar image trapongx
32 3

updated 2017-04-04 17:42:49 +0800

Thank you so much, chillworld, for your answer.

I checked for event firing from client the same way as you checked. In Chrome, "Inspect" then "network".

I found lang-addon.xml in zkbind-8.0.2.2.jar as you mentioned. I removed the Java annotation from JpaTextbox and added the XML annotation in my ownlang-addon.xml like you post above. It works also.

<?xml version="1.0" encoding="UTF-8"?>
<language-addon>
    <addon-name>myzkcomp</addon-name>
      <version>
      <version-class>net.bitreplay.Version</version-class>
      <version-uid>1.0-SNAPSHOT</version-uid>
      <zk-version>8.0.2.2</zk-version><!--

or later --> </version>

  <language-name>xul/html</language-name>

  <component>
      <component-name>jpatextbox</component-name>
      <component-class>net.bitreplay.JpaTextbox</component-class>
      <extends>textbox</extends>
      <annotation>
          <annotation-name>ZKBIND</annotation-name>
          <property-name>value</property-name>
          <attribute>
              <attribute-name>ACCESS</attribute-name>
              <attribute-value>both</attribute-value>
          </attribute>
          <attribute>
              <attribute-name>SAVE_EVENT</attribute-name>
              <attribute-value>onChange</attribute-value>
          </attribute>
          <attribute>
              <attribute-name>LOAD_REPLACEMENT</attribute-name>
              <attribute-value>rawValue</attribute-value>
          </attribute>
          <attribute>
              <attribute-name>LOAD_TYPE</attribute-name>
              <attribute-value>java.lang.String</attribute-value>
          </attribute>
      </annotation>
      <annotation>
          <annotation-name>ZKBIND</annotation-name>
          <property-name>errorMessage</property-name>
          <attribute>
              <attribute-name>ACCESS</attribute-name>
              <attribute-value>load</attribute-value>
          </attribute>
          <attribute>
              <attribute-name>CONVERTER</attribute-name>
              <attribute-value>org.zkoss.bind.converter.sys.ErrorMessageConverter</attribute-value>
          </attribute>
      </annotation>
  </component>
</language-addon>

Anyway, without this annotation it does not work for me while it work for you. So I inspect the LanguageDefinition using breakpoint debugger and what I get from (It's kotlin syntax)

LanguageDefinition._ldefByName.get("xul/html")._compdefs.get("textbox")._annots

is

[annot:{value={ZKBIND=[@ZKBIND(ACCESS=[both], SAVE_EVENT=[onChange], LOAD_REPLACEMENT=[rawValue], LOAD_TYPE=[java.lang.String])], default-bind=[@default-bind(access=[both], save-when=[self.onChange])]}, errorMessage={ZKBIND=[@ZKBIND(ACCESS=[load], CONVERTER=[org.zkoss.bind.converter.sys.ErrorMessageConverter])]}}]

And from

LanguageDefinition._ldefByName.get("xul/html")._compdefs.get("jpatextbox")._annots

I get null.

Is this the expected thing?

Below is the whole of my Gradle build file. I don't want to bother you too much so unless you are curious enough, please just ignore it.

buildscript {
    ext {
        kotlinVersion = '1.1.1'
        kotlinPluginVersion = '1.1.1'
        springBootVersion = '1.5.1.RELEASE'
        zkVersion = '8.0.2.2'
        zkSpringVersion = '3.2.0'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinPluginVersion}")
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinPluginVersion}")
    }
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse-wtp'
apply plugin: 'org.springframework.boot'
apply plugin: 'war'

war {
    baseName = 'londrikt'
    version = '0.0.1-SNAPSHOT'
}

sourceCompatibility = 1.8

repositories {
    mavenCentral()
    maven { url 'http://mavensync.zkoss.org/maven2' }
    maven { url 'http://mavensync.zkoss.org/eval' }
    jcenter()
}

configurations {
    providedRuntime
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-aop')
    compile('org.springframework.boot:spring-boot-starter-cache')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-jdbc')
    compile('org.springframework.boot:spring-boot-starter-mail')
    compile('org.springframework.boot:spring-boot-starter-security')
    compile('org.springframework.boot:spring-boot-starter-social-facebook')
    compile('org.springframework.boot:spring-boot-starter-validation')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
    compile("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
    runtime('org.springframework.boot:spring-boot-devtools')
    runtime('com.h2database:h2')
    runtime('mysql:mysql-connector-java')
    //providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
    testCompile('org.springframework.boot:spring-boot-starter-test')

    compile("org.zkoss.zk:zkbind:8.0.2.2")
    compile("org.zkoss.zk:zul:8.0.2.2")
    compile("org.zkoss.zk:zuti:8.0.2.2-Eval")
    compile("org.zkoss.zk:zkmax:8.0.2.2-Eval")
    compile("org.zkoss.zk:zkex:8.0.2.2-Eval")
    compile("org.zkoss.zk:zkplus:8.0.2.2")
    compile("org.zkoss.zk:zhtml:8.0.2.2")
    compile("org.zkoss.zk:zkspring-core:3.2.0")

    compile("au.com.console:kotlin-jpa-specification-dsl:0.1.0")

    //runtime("org.hibernate:hibernate-validator:4.0.2.GA")
}
link publish delete flag offensive edit

Comments

It's Mduchemin who answered your question, not me ;)

chillworld ( 2017-04-04 20:49:16 +0800 )edit
Your answer
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
2 followers

RSS

Stats

Asked: 2017-04-03 16:55:17 +0800

Seen: 57 times

Last updated: Apr 05 '17

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