Skip to content

Commit 39289a6

Browse files
committed
register EventListener via EventHandlerRegistration (and unregister on @PreDestroy)
1 parent 2a03312 commit 39289a6

File tree

4 files changed

+120
-5
lines changed

4 files changed

+120
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright © 2023 Treblereel
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package io.crysknife.ui.templates.client;
16+
17+
import elemental2.dom.EventListener;
18+
import elemental2.dom.HTMLElement;
19+
20+
import java.util.Objects;
21+
22+
public class EventHandlerHolder {
23+
24+
25+
final String eventType;
26+
final HTMLElement element;
27+
final EventListener eventListener;
28+
29+
public EventHandlerHolder(String eventType, HTMLElement element, EventListener eventListener) {
30+
this.eventType = eventType;
31+
this.element = element;
32+
this.eventListener = eventListener;
33+
}
34+
35+
public EventHandlerHolder attach() {
36+
element.addEventListener(eventType, eventListener);
37+
return this;
38+
}
39+
40+
public EventHandlerHolder remove() {
41+
element.removeEventListener(eventType, eventListener);
42+
return this;
43+
}
44+
45+
@Override
46+
public int hashCode() {
47+
return Objects.hash(eventType, element, eventListener);
48+
}
49+
50+
@Override
51+
public boolean equals(Object o) {
52+
if (this == o)
53+
return true;
54+
if (o == null || getClass() != o.getClass())
55+
return false;
56+
EventHandlerHolder that = (EventHandlerHolder) o;
57+
return Objects.equals(eventType, that.eventType) && Objects.equals(element, that.element)
58+
&& Objects.equals(eventListener, that.eventListener);
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright © 2023 Treblereel
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package io.crysknife.ui.templates.client;
16+
17+
import java.util.ArrayList;
18+
import java.util.HashMap;
19+
import java.util.List;
20+
import java.util.Map;
21+
22+
public class EventHandlerRegistration {
23+
24+
private final Map<Object, List<EventHandlerHolder>> handlers = new HashMap<>();
25+
26+
public void add(Object instance, EventHandlerHolder handler) {
27+
handlers.computeIfAbsent(instance, k -> new ArrayList<>()).add(handler.attach());
28+
}
29+
30+
public void remove(Object key, EventHandlerHolder handler) {
31+
handlers.get(key).remove(handler.remove());
32+
}
33+
34+
public void clear(Object instance) {
35+
List<EventHandlerHolder> handlers = this.handlers.get(instance);
36+
for (EventHandlerHolder eventHandlerHolder : handlers) {
37+
eventHandlerHolder.remove();
38+
}
39+
handlers.clear();
40+
this.handlers.remove(instance);
41+
}
42+
43+
}

ui/templates/generator/src/main/java/io/crysknife/ui/templates/generator/TemplateGenerator.java

+12
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@
2929
import com.google.auto.common.MoreTypes;
3030
import com.google.common.base.Splitter;
3131
import com.google.common.base.Strings;
32+
import com.google.common.base.Supplier;
3233
import com.google.common.escape.Escaper;
3334
import com.google.common.escape.Escapers;
3435
import com.inet.lib.less.Less;
3536
import elemental2.dom.DomGlobal;
37+
import elemental2.dom.EventListener;
3638
import elemental2.dom.HTMLElement;
3739
import freemarker.template.Configuration;
3840
import freemarker.template.Template;
@@ -50,6 +52,8 @@
5052
import io.crysknife.generator.context.IOCContext;
5153
import io.crysknife.generator.helpers.MethodCallGenerator;
5254
import io.crysknife.logger.TreeLogger;
55+
import io.crysknife.ui.templates.client.EventHandlerHolder;
56+
import io.crysknife.ui.templates.client.EventHandlerRegistration;
5357
import io.crysknife.ui.templates.client.StyleInjector;
5458
import io.crysknife.ui.templates.client.TemplateUtil;
5559
import io.crysknife.ui.templates.client.annotation.DataField;
@@ -252,13 +256,17 @@ private void code(ClassMetaInfo builder, BeanDefinition beanDefinition,
252256

253257
processDataFields(templateContext, templateDefinition);
254258
processEventHandlers(beanDefinition, templateContext, templateDefinition);
259+
processOnDestroy(builder);
255260
}
256261

257262
private void addImports(ClassMetaInfo builder) {
258263
builder.addImport(DomGlobal.class);
259264
builder.addImport(Js.class);
260265
builder.addImport(Reflect.class);
261266
builder.addImport(TemplateUtil.class);
267+
builder.addImport(EventListener.class);
268+
builder.addImport(EventHandlerHolder.class);
269+
builder.addImport(EventHandlerRegistration.class);
262270
}
263271

264272
private void setInnerHTML(TemplateContext templateContext,
@@ -347,6 +355,10 @@ private void processEventHandlers(BeanDefinition beanDefinition, TemplateContext
347355
}
348356
}
349357

358+
private void processOnDestroy(ClassMetaInfo builder) {
359+
builder.addToOnDestroy((Supplier<String>) () -> "eventHandlerRegistration.clear(instance);");
360+
}
361+
350362
private void setStylesheet(ClassMetaInfo builder, TemplateContext templateContext,
351363
TemplateDefinition templateDefinition) {
352364
if (templateContext.getStylesheet() != null) {

ui/templates/generator/src/main/resources/templates/ui.ftlh

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ private interface HTMLElementAccessor {
44
elemental2.dom.HTMLElement getElement();
55
}
66
</#if>
7+
private final EventHandlerRegistration eventHandlerRegistration = new EventHandlerRegistration();
78

8-
9-
private void setAndInitTemplate() {
9+
private void setAndInitTemplate() {
1010
<#if css??>
11-
StyleInjector.fromString("${css?no_esc}").inject();
11+
StyleInjector.fromString("${css?no_esc}").inject();
1212
</#if>
1313
<#if initRootElement>
1414
elemental2.core.Reflect.set(instance, "__root_element__", elemental2.dom.DomGlobal.document.createElement("div"));
@@ -44,9 +44,9 @@ private void setAndInitTemplate() {
4444

4545
<#list events as event>
4646
<#list event.eventTypes as type>
47-
((elemental2.dom.HTMLElement) Js.asPropertyMap(instance).get(Reflect.objectProperty("${event.mangleName}", instance))).addEventListener("${type}", (e) -> {
47+
eventHandlerRegistration.add(instance, new EventHandlerHolder("${type}", ((elemental2.dom.HTMLElement) Js.asPropertyMap(instance).get(Reflect.objectProperty("${event.mangleName}", instance))), (e) -> {
4848
${event.call?no_esc}
49-
});
49+
}));
5050
</#list>
5151
</#list>
5252
}

0 commit comments

Comments
 (0)