Skip to content

Commit

Permalink
Added enhancments
Browse files Browse the repository at this point in the history
  • Loading branch information
mstahv committed Aug 21, 2024
1 parent 5804d80 commit 9ed4ee5
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 33 deletions.
52 changes: 50 additions & 2 deletions src/main/java/org/vaadin/addons/velocitycomponent/VElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.function.SerializableConsumer;
import com.vaadin.flow.shared.Registration;
Expand All @@ -21,6 +22,10 @@ private VElement(Element element) {
this.element = element;
}

public static VElement body() {
return new VElement(UI.getCurrent().getElement());
}

public static VElement of(Element element) {
return new VElement(element);
}
Expand All @@ -43,11 +48,11 @@ public <T> Registration on(Class<T> eventType, SerializableConsumer<T> listener)
if(simpleName.endsWith("Event")) {
simpleName = simpleName.substring(0, simpleName.length() - 5);
}
String kebabCased = stream(StringUtils.splitByCharacterTypeCamelCase(simpleName))
String eventName = stream(StringUtils.splitByCharacterTypeCamelCase(simpleName))
.map(s -> s.toLowerCase())
.reduce((a, b) -> a + "-" + b).get();

return element.addEventListener(kebabCased, event -> {
return element.addEventListener(eventName, event -> {
JsonValue jsonValue = event.getEventData().get("event.detail");
T value;
if(jsonValue.getType() == JsonType.OBJECT) {
Expand All @@ -66,4 +71,47 @@ public <T> Registration on(Class<T> eventType, SerializableConsumer<T> listener)
listener.accept(value);
}).addEventData("event.detail");
}

/**
* Listen to a custom client side event and receive the payload in "event.detail".
* If the event type/payload is not String, Integer, Double or Boolean, it is expected to be a JSON
* and deserialized to the event type using Jackson ObjectMapper.
*
* On the client side, the event should be dispatched with a CustomEvent with the detail property.
*
* @param eventName the name of the event
* @param eventType the DTO of the "event.detail"
* @param listener the listener to be called when the event is fired
* @return a registration that can be used to remove the listener
* @param <T> the type of the event
*/
public <T> Registration on(String eventName, Class<T> eventType, SerializableConsumer<T> listener) {
return element.addEventListener(eventName, event -> {
JsonValue jsonValue = event.getEventData().get("event.detail");
T value;
if(eventType == String.class) {
value = (T) jsonValue.asString();
} else if(eventType == Integer.class) {
value = (T) Integer.valueOf((int) jsonValue.asNumber());
} else if(eventType == Double.class) {
value = (T) Double.valueOf(jsonValue.asNumber());
} else if(eventType == Boolean.class) {
value = (T) Boolean.valueOf(jsonValue.asBoolean());
} else if(jsonValue.getType() == JsonType.OBJECT) {
try {
value = objectMapper.readValue(jsonValue.toJson(), eventType);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
try {
value = objectMapper.readValue(jsonValue.asString().toString(), eventType);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
listener.accept(value);
}).addEventData("event.detail");
}

}
111 changes: 80 additions & 31 deletions src/test/java/org/vaadin/addons/usageexample/VElementView.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,98 @@
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import org.vaadin.addons.velocitycomponent.VElement;

@Route
public class VElementView extends VerticalLayout {

public record FooBar(String foo, String bar, String car) {}
public VElementView() {
add(new H1("Example to listen DOM events easily!"));

public VElementView() {
add(new H1("Example to listen DOM events easily!"));
VElement.of(getElement()).on(FooBar.class, event -> {
String bar = event.bar();
add(new Paragraph("Received foo-bar event with detail: " + event));
});
// Event name can also be specified explicitly
VElement.of(getElement()).on("foo-car", FooBar.class, event -> {
String bar = event.bar();
add(new Paragraph("Received foo-car event with detail: " + event));
});
VElement.of(getElement()).on("string-msg", String.class, event -> {
add(new Paragraph("Received string-msg event with detail: " + event));
});
VElement.of(getElement()).on("boolean-msg", String.class, event -> {
add(new Paragraph("Received boolean-msg event with detail: " + event));
});
VElement.of(getElement()).on("int-msg", Integer.class, event -> {
add(new Paragraph("Received int-msg event with detail: " + event));
});
VElement.of(getElement()).on("double-msg", Double.class, event -> {
add(new Paragraph("Received double-msg event with detail: " + event));
});

VElement.of(getElement()).on(FooBar.class, event -> {
String bar = event.bar();
add(new Paragraph("Received foo-bar event with detail: " + event));
});

add(new Button("Click me", e -> {
add(new HorizontalLayout(
new Button("Click me", e -> {
getElement().executeJs("""
this.dispatchEvent(new CustomEvent('foo-bar', {
detail: {
foo: 'foo',
bar: 'bar',
car: 'car'
}
}));
""");
}));

add(new Button("Click me too", e -> {
this.dispatchEvent(new CustomEvent('foo-bar', {
detail: {
foo: 'foo',
bar: 'bar',
car: 'car'
}
}));
""");
}),
new Button("Click me too", e -> {
// This is in theory bit more efficient for the server
// as it does not need to deserialize-serialize (with GWT library)
// and then desirialize with Jackson, but only once with Jackson
getElement().executeJs("""
this.dispatchEvent(new CustomEvent('foo-bar', {
detail: JSON.stringify({
foo: 'foo',
bar: 'bar',
car: 'car'
})
}));
""");
}));

}
this.dispatchEvent(new CustomEvent('foo-car', {
detail: JSON.stringify({
foo: 'foo',
bar: 'bar',
car: 'car'
})
}));
""");
}),
new Button("Fire string", e -> {
getElement().executeJs("""
this.dispatchEvent(new CustomEvent('string-msg', {
detail: 'foo'
}));
""");
}),
new Button("Fire boolean", e -> {
getElement().executeJs("""
this.dispatchEvent(new CustomEvent('boolean-msg', {
detail: true
}));
""");
}),
new Button("Fire int", e -> {
getElement().executeJs("""
this.dispatchEvent(new CustomEvent('int-msg', {
detail: 1
}));
""");
}),
new Button("Fire double", e -> {
getElement().executeJs("""
this.dispatchEvent(new CustomEvent('double-msg', {
detail: 1.2345
}));
""");
})
));


}

public record FooBar(String foo, String bar, String car) {
}
}

0 comments on commit 9ed4ee5

Please sign in to comment.