I'm developing a GWT widget for an existing vaadin application and so far everything has worked out fine, until I needed to call a server-side function from the client and get a value from it to the client.
more detailed issue: There is a server-side function that gets certain values from a connected database. Now I want to get access this function from the client-side, since I need the values to update something in the widget.
According to Vaadin and GWT documentations you're supposed to use RPC for this, and I already implemented multiple functions on the server-side that bascially do the opposite (send something from the server to the client, initiate a call of a client function from server code etc.)
From my understanding I'm supposed to call a void return function on the server by using rpc (the part I can't get to work) then I could make that function on the server use a server=>client rpc to send that value back to the client (already working)
Is this the definite solution and if so how do I properly implement the client=>server part and if not, what would be a good solution?
I've already tried something like https://vaadin.com/wiki/-/wiki/Main/Sending+events+from+the+client+to+the+server+using+RPC but somehow can't figure out how to call the method while in the widget class and not in the connector class There just seems to be something missing? and is this even the right approach?
parts of the current code:
DrawwServerRPC
public interface DrawwServerRPC extends ServerRpc {
public void updateE(String e);
}
relevant part of Draww.java on server
protected DrawwServerRPC = new DrawwServerRPC () {
public void updateE(String e){
// gets some values from a db and then sends them back to the client
// via rpc (both points working fine)
}
};
public Draww() {
registerRpc(rpc);
}
part of the connector class, this is supposed to be called when a specific method in the DrawwWidget class (client) is called, instead of on a click
getWidget().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
final MouseEventDetails mouseDetails = MouseEventDetailsBuilder
.buildMouseEventDetails(event.getNativeEvent(),
getWidget().getElement());
rpc.updateE("test");
}
});
So my main issue is, how do I now properly access this method (most likely over the connector method) when a specific function in the DrawwWidget class on the Client is called?
And how do I then pass the value from the client method to the connector (or even server side) method? => need to somehow call the updateE method on the server from client side code (by using connector/rpc)
edit: so here is a bit longer explanation of how I solved it in the end according to the idea I got from Mika's answer and this
added an Interface
public interface customListener {
void customEvent (String s);
}
adjusted the DrawwWidget:
public class DrawwWidget extends Label{
private customListener MyListener;
//...
private void someFunction() {
String something = ...;
if (myListener != null) myListener.customEvent(something);
}
public void setMyListener(customListener listener) {
this.myListener = listener;
}
}
and finally implemented the listener in the connector class:
public class DrawwConnector extends AbstractComponentConnector implements customListener {
DrawwServerRpc rpc = RpcProxy.create(DrawwServerRpc.class, this);
public DrawwConnector () {
//lots of irrelevant Server => Client rpc things
getWidget().setMyListener(this);
}
@Override
public void customEvent(String s) {
rpc.doSomething(s);
}
Now I can call the server side "doSomething" method from wherever I want in the widget by using the "customEvent (String s)" Method
You can interact with client side with custom widgets or javascript extensions. For visible components custom widget is usually suitable solution.
You can follow similar convention in client side as Vaadin generally follows in server side and register a listener from connector to your widget. For example:
@Override
protected Widget createWidget() {
MyWidget widget = GWT.create(MyWidget.class);
widget.addMyListener(new MyListener() {
@Override
public void onSomeEvent(ClientData data) {
rpc.onEventFromClient(data);
}
});
return widget;
}
Widget is a GWT component and usually you can find some existing GWT component that you can extend. If not, then it is possible to create plain HTML elements from the widget, good reference for this is the source code for existing GWT components.
Here is an example of a widget that has a text and you can click on the widget.
import com.google.gwt.user.client.ui.Label;
// ... only relevant imports included
public class MyWidget extends Label {
private List<MyListener> listeners = new ArrayList<MyListener>();
public MyWidget() {
addStyleName("m-my-label");
// Add GWT event listeners for events that you want to capture.
addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
notifyListeners();
}
});
}
private void notifyListeners() {
for (MyListener listener : listeners) {
listener.onSomeEvent(new ClientData("Hello from widget"));
}
}
}