Leather_Dog
(Leather Dog Muksihs)
October 12, 2018, 1:09am
1
How can one provide a callback function to a javascript function call that will callback to the server side?
I’ve tried: (but it doesn’t work… can’t serialize the wanted callback to json… which I’m wanting a javascript function passed as the argument anyways)
Page page = UI.getCurrent().getPage();
SerializableBiConsumer<JsonValue, JsonValue> callback=new SerializableBiConsumer<JsonValue, JsonValue>() {
@Override
public void accept(JsonValue error, JsonValue result) {
//do stuff
}
};
page.executeJavaScript("steem.api.getDynamicGlobalProperties($0);", callback);
Leather_Dog
(Leather Dog Muksihs)
October 12, 2018, 6:24pm
2
ok, I’ve come up with the following “hack”. Is there a better way?
I do the following in the test project view:
ExecuteWithCallback withCallback = new ExecuteWithCallback(jsonValues -> {
int ix = 0;
for (JsonValue value : jsonValues) {
TextArea textArea = new TextArea("JSON RECEIVED [" + (++ix) + "]
");
if (value == null) {
textArea.setValue("[NULL]
");
} else {
textArea.setValue(value.toJson());
textArea.setWidth("98%");
}
SteemVaadinView.this.add(textArea);
}
});
add(withCallback);
withCallback.call();
Using the following to execute the global javascript and have its callback hit the server.
package com.muksihs.vaadin.steem;
import com.vaadin.flow.component.ClientCallable;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.dom.Style;
import elemental.json.Json;
import elemental.json.JsonObject;
import elemental.json.JsonValue;
@SuppressWarnings("serial")
@Tag("script")
public class ExecuteWithCallback extends Component {
private static int counter=0;
private final int me;
private final String id;
private final ExecuteWithCallback.JsonvalueCallback callback;
public ExecuteWithCallback(ExecuteWithCallback.JsonvalueCallback callback) {
this.callback = callback;
me = ++counter;
id=this.getClass().getName()+"-"+(me);
Style style = this.getElement().getStyle();
style.set("display", "none");
this.setId(id);
}
public static interface JsonvalueCallback {
void onCallback(JsonValue... jsonValues);
}
public void call() {
JsonObject query = Json.createObject();
query.put("tag", "leatherdog-games");
query.put("limit", 2);
UI.getCurrent().getPage().executeJavaScript("steem.api.getDiscussionsByBlog($0,document.getElementById(\""+id+"\").$server.callback)", query);
}
@ClientCallable
private void callback(JsonValue... jsonValues) {
System.out.println("=== CALLBACK ... "+(jsonValues==null?"NULL":jsonValues.length));
if (callback!=null) {
callback.onCallback(jsonValues);
}
getElement().removeFromParent();
}
}
Leather_Dog
(Leather Dog Muksihs)
October 13, 2018, 1:50am
3
I’ve worked out my hack to be something more general purpose in use:
See: https://github.com/muksihs/steem-vaadin/tree/7abe11d5b0d5f8745b423b04417c9d91667248fd
The utility routines are JsExecuteThen, JsWithArrayCallback, and JsWithCallback.
A couple of basic examples are in the file SteemVaadinView.java
Basically, a component is created for each execute to provide a callback hook, then the getPage javascript executor is called with the hooks provided as the callback/then/catch functions as arguments to the function call.
After the callback completes on the server side, the element for the component is removed.
Leather_Dog
(Leather Dog Muksihs)
October 14, 2018, 3:55am
4