Event Handling
There are three scenarios in which the use of Event Handlers is different in the Kotlin API:
- Event handlers in common props - event handlers are replaced by lambdas configured via
Style
. - Providing
EventHandler
s to existing Spec components - when anEventHandler
is expected, lambda should be wrapped witheventHandler {}
oreventHandlerWithReturn {}
. - Accepting custom event handlers - custom Event classes are replaced by lambdas passed as props.
Each of these scenarios is detailed in the following sections.
Supplying event handlersβ
Event handlers in common propsβ
Event handlers that were exposed in common props in the Spec API (such as clickHandler
) are now provided via Style
.
Style
properties accept lambdas instead of generated EventHandler
objects.
- Kotlin API
- Spec API
class EventComponent : KComponent() {
override fun ComponentScope.render(): Component? {
return Column(
style = Style.onClick { onClick() }.width(80.dp).height(80.dp).backgroundColor(YELLOW))
}
}
private fun onClick() {
Log.d("EventComponent", "click")
}
@LayoutSpec
public class EventComponentSpec {
@OnCreateLayout
static Component onCreateLayout(ComponentContext c) {
return Column.create(c)
.clickHandler(EventComponent.onClickEvent(c))
.widthDip(80)
.heightDip(80)
.backgroundColor(YELLOW)
.build();
}
@OnEvent(ClickEvent.class)
static void onClickEvent(ComponentContext c) {
Log.d("EventComponentSpec", "click");
}
}
Providing EventHandler
s to existing Spec componentsβ
When using pre-existing Spec components or Sections that accept EventHandler
objects for custom events (such as RenderEvent
in DataDiffSection
), you should use either eventHandler()
or eventHandlerWithReturn()
, depending on whether the custom event class declares a returnType
in its @Event
annotation or not. Both of these functions accept a lambda, which is invoked when the event occurs.
- Kotlin API
- Spec API
class SectionComponent(private val words: List<String>) : KComponent() {
override fun ComponentScope.render(): Component? {
return Column(style = Style.width(80.dp).height(80.dp)) {
child(
RecyclerCollectionComponent(
section =
DataDiffSection.create<String>(SectionContext(context))
.data(words)
.renderEventHandler(eventHandlerWithReturn { event -> onRender(event) })
.build()))
}
}
private fun ResourcesScope.onRender(event: RenderEvent<String>): RenderInfo {
return ComponentRenderInfo.create().component(Text(text = event.model)).build()
}
}
@LayoutSpec
class SectionComponentSpec {
@OnCreateLayout
static Component onCreateLayout(ComponentContext c, @Prop List<String> words) {
return Column.create(c)
.widthDip(80)
.heightDip(80)
.child(
RecyclerCollectionComponent.create(c)
.section(
DataDiffSection.<String>create(new SectionContext(c))
.data(words)
.renderEventHandler(SectionComponent.onRender(c))))
.build();
}
@OnEvent(RenderEvent.class)
static RenderInfo onRender(ComponentContext context, @FromEvent String model) {
return ComponentRenderInfo.create().component(Text.create(context).text(model)).build();
}
}
Accepting custom event handlersβ
In the Spec API, custom event handlers can be defined by creating an Event class, and then either providing its type to the events
param in the @LayoutSpec
annotation or accepting an EventHandler
as a prop, as detailed in the Events for Specs page. In the Kotlin API, simply accept a lambda as a prop to be invoked when the event happens:
- Kotlin API
- Spec API
class ClickEventComponent(
private val onButtonClicked: (String) -> Unit,
) : KComponent() {
override fun ComponentScope.render(): Component {
return Column {
child(Text(text = "OK", style = Style.onClick { onButtonClicked("OK clicked") }))
child(Text(text = "Cancel", style = Style.onClick { onButtonClicked("Cancel clicked") }))
}
}
}
@LayoutSpec(events = {ClickTextEvent.class})
class ClickEventComponentSpec {
@OnCreateLayout
static Component onCreateLayout(ComponentContext c) {
return Column.create(c)
.child(Text.create(c).text("OK").clickHandler(ClickEventComponent.onButtonClick(c, "OK")))
.child(
Text.create(c)
.text("Cancel")
.clickHandler(ClickEventComponent.onButtonClick(c, "Cancel")))
.build();
}
@OnEvent(ClickEvent.class)
protected static void onButtonClick(ComponentContext c, @Param String text) {
EventHandler handler = ClickEventComponent.getClickTextEventHandler(c);
if (handler != null) {
ClickEventComponent.dispatchClickTextEvent(handler, text);
}
}
}