Search code examples
knockout.jsdukescript

How can I define writable computed observables in Dukescript?


I'm trying to replicate the example 1 on Dukescript, the example consists on modifying the generated full name and automatically modify the first name and last name fields on the data model.

This is my code so far

HTML:

<div>First name: <span data-bind="text: firstName, valueUpdate: input"></span></div>
<div>Last name: <span data-bind="text: lastName, valueUpdate: input"></span></div>
<div class="heading">Hello, <input data-bind="textInput: fullName, valueUpdate: afterkeydown,event: { keyup: fullName() }
"/></div>

Java:

package org.javapro.dukescript;

import net.java.html.json.Model;
import net.java.html.json.ComputedProperty;
import net.java.html.json.Property;
import net.java.html.json.Function;
import java.util.regex.Pattern;


@Model (targetId="",className = "WritableComputed", properties = {
    @Property (name = "firstName", type=String.class)
   ,@Property (name = "lastName", type=String.class)
})
class MyClass {

  @ComputedProperty static String fullName(String firstName, String lastName) {
    return firstName + " " + lastName;
  }

  @Function
  static void fullName(WritableComputed model, String value) {
    int lastSpacePos = value.lastIndexOf(" ");
            // Ignore values with no space character
            if (lastSpacePos > 0) {
              // Update "firstName"
                model.setFirstName(value.substring(0, lastSpacePos)); 
              // Update "lastName"
                model.setLastName(value.substring(lastSpacePos + 1)); 
            }
  }

  public static void main(String args[]){
    WritableComputed wc = new WritableComputed("hello","world");
    wc.applyBindings();
  }
}

The problem is that the text field only renders a js function

function(c,k){var e=b.ko4j;e&&d.java_lang_Class(!1).toJS(d.org_netbeans_html_ko4j_$JsCallbacks$(!1)._VM().org_1netbeans_1html_1ko4j_1Knockout$call$ILjava_1lang_1Object_12Ljava_1lang_1Object_12__Ljava_lang_Object_2Lorg_netbeans_html_ko4j_Knockout_2ILjava_lang_Object_2Ljava_lang_Object_2(e,a,c,k))}

Thank you in advance.


Solution

  • It turns out that even if by default computed properties are read only, you can make them editable by specifying a function on the annotation @ComputedProperty which receives the Data Model as parameter and the data that will be used to mutate.

    HTML:

    <div>First name: <span data-bind="text: firstName, valueUpdate: input"></span></div>
    <div>Last name: <span data-bind="text: lastName, valueUpdate: input"></span></div>
    <div class="heading">Hello, <input data-bind="textInput: fullName"/></div>
    

    Java:

    package org.javapro.dukescript;
    
    import net.java.html.json.Model;
    import net.java.html.json.ComputedProperty;
    import net.java.html.json.Property;
    import net.java.html.json.Function;
    import java.util.regex.Pattern;
    
    
    @Model (targetId="",className = "WritableComputed", properties = {
        @Property (name = "firstName", type=String.class)
       ,@Property (name = "lastName", type=String.class)
    })
    class MyClass {
    
      @ComputedProperty(write="setFullName")
      static String fullName(String firstName, String lastName) {
        return firstName + " " + lastName;
      }
    
      static void setFullName(WritableComputed model, String value) {
        int lastSpacePos = value.lastIndexOf(" ");
                // Ignore values with no space character
                if (lastSpacePos > 0) {
                  // Update "firstName"
                    model.setFirstName(value.substring(0, lastSpacePos)); 
                  // Update "lastName"
                    model.setLastName(value.substring(lastSpacePos + 1)); 
                }
      }
    
      public static void main(String args[]){
        WritableComputed wc = new WritableComputed("hello","world");
        wc.applyBindings();
      }
    }