X

Geertjan's Blog

  • May 16, 2015

Porting Knockout Components to DukeScript

Geertjan Wielenga
Product Manager

With Knockout, you can extend the DOM by means of widgets, also known as 'components', such as the "user" component that you see below, which has the parameters "firstName" and "lastName":

As discussed yesterday and the day before in this blog, a component is created in JavaScript, like this:

ko.components.register('user', {
viewModel: function (params) {
this.firstName = ko.observable(params.firstName);
this.lastName = ko.observable(params.lastName);
this.fullName = ko.pureComputed(function () {
return this.firstName() + " " + this.lastName();
}, this);
},
template:
'First Name: <input data-bind="textInput: firstName"/>\
<br/>\
Last Name: <input data-bind="textInput: lastName"/>\
<h2 data-bind="text: fullName"></h2>'
});

As you can see here, by means of 'ko.components.register', you're able to register a new component, which is named 'user' here, consisting of a viewmodel and a template.

Now let's imagine we're using DukeScript, i.e., the WORA framework for Java programmers. Imagine you have several Knockout components like the above, how would you integrate them into your DukeScript application?

One of the Maven projects provided by the DukeScript Maven archetype has "JavaScript Libraries" in its name:

Notice that in the above there's a JavaScript file named 'userEntryComponent.js'. The content of that file is the 'user' component described in code at the start of this blog entry. Also notice that there is a Java source file in the above screenshot, named 'UserEntryWidget.java', which has this content:

package org.demo.ko4j.DemoKO4J.js;
import net.java.html.js.JavaScriptBody;
import net.java.html.js.JavaScriptResource;
@JavaScriptResource(value = "userEntryComponent.js")
public final class UserEntryWidget {
private UserEntryWidget() {
}
@JavaScriptBody(args = {}, body = "")
public static native void registerComponent();
}

Notice that there is a reference to the JavaScript file, as well as a static method named 'registerComponent'.

OK, congratulations, you have ported your Knockout component to DukeScript, which consists of (1) copying the JavaScript file into the correct place in the DukeScript application structure and (2) registering it via the @JavaScriptResource annotation shown above.

The final step is to use the component. In the 'Main.java' class, i.e., in the Maven project where the client code is defined, you need the following:

public static void onPageLoad() throws Exception {
Data d = new Data();Models.toRaw(d); // this line is required to initialize knockout
UserEntryWidget.registerComponent();

d.applyBindings();
}

Notice the two lines in bold above. Notice that we're calling the static method in the UserEntryWidget class above. Also notice that we do not initialize the Data class above, i.e., we do not need to use 'setFirstName' and 'setLastName' on the Data class, because the initialization is done when you make use of the 'user' component, as you can see in the first screenshot above.

That's all you need to do to include a Knockout component in a DukeScript application.

Join the discussion

Comments ( 1 )
  • guest Wednesday, June 3, 2015

    Thank yout for the example, I'm trying to understand how the JavaScript domain and the Java domain can interact in DukeScript.

    You mentioned the methods 'setFirstName' and 'setLastName' in the Data class.

    Is a Java model in the Data class automatically generated from the js resource by @JavaScriptResource annotation?

    From what I've seen so far Java code can access JavaScript code via the Data class, while JavaScript can access Java variables (inside knockout components) via the $root scope.

    This case seems to be more a seemless transition from traditional knockout in javascript, because the model is not defined inside the @Model java annotation, which is more verbose.


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.