diff --git a/flow-client/src/main/java/com/vaadin/client/flow/binding/SimpleElementBindingStrategy.java b/flow-client/src/main/java/com/vaadin/client/flow/binding/SimpleElementBindingStrategy.java index 9bc48a15a1f..06de0201c3d 100644 --- a/flow-client/src/main/java/com/vaadin/client/flow/binding/SimpleElementBindingStrategy.java +++ b/flow-client/src/main/java/com/vaadin/client/flow/binding/SimpleElementBindingStrategy.java @@ -284,9 +284,9 @@ private native void bindPolymerModelProperties(StateNode node, private native void hookUpPolymerElement(StateNode node, Element element) /*-{ var self = this; - + var originalPropertiesChanged = element._propertiesChanged; - + if (originalPropertiesChanged) { element._propertiesChanged = function (currentProps, changedProps, oldProps) { $entry(function () { @@ -295,16 +295,16 @@ private native void hookUpPolymerElement(StateNode node, Element element) originalPropertiesChanged.apply(this, arguments); }; } - - + + var tree = node.@com.vaadin.client.flow.StateNode::getTree()(); - + var originalReady = element.ready; - + element.ready = function (){ originalReady.apply(this, arguments); @com.vaadin.client.PolymerUtils::fireReadyEvent(*)(element); - + // The _propertiesChanged method which is replaced above for the element // doesn't do anything for items in dom-repeat. // Instead it's called with some meaningful info for the dom-repeat element. @@ -313,7 +313,7 @@ private native void hookUpPolymerElement(StateNode node, Element element) // which changes this method for any dom-repeat instance. var replaceDomRepeatPropertyChange = function(){ var domRepeat = element.root.querySelector('dom-repeat'); - + if ( domRepeat ){ // If the dom-repeat element is in the DOM then // this method should not be executed anymore. The logic below will replace @@ -327,12 +327,12 @@ private native void hookUpPolymerElement(StateNode node, Element element) // if dom-repeat is found => replace _propertiesChanged method in the prototype and mark it as replaced. if ( !domRepeat.constructor.prototype.$propChangedModified){ domRepeat.constructor.prototype.$propChangedModified = true; - + var changed = domRepeat.constructor.prototype._propertiesChanged; - + domRepeat.constructor.prototype._propertiesChanged = function(currentProps, changedProps, oldProps){ changed.apply(this, arguments); - + var props = Object.getOwnPropertyNames(changedProps); var items = "items."; for(i=0; ifalse initially. // in this case dom-repeat is not yet in the DOM tree until dom-if becomes true @@ -389,7 +389,7 @@ private native void hookUpPolymerElement(StateNode node, Element element) element.addEventListener('dom-change',replaceDomRepeatPropertyChange); } } - + }-*/; private static void handleListItemPropertyChange(double nodeId, @@ -1153,16 +1153,21 @@ private void remove(JsArray listeners, BindingContext context, private EventRemover bindDomEventListeners(BindingContext context) { NodeMap elementListeners = getDomEventListenerMap(context.node); - elementListeners.forEachProperty((property, - name) -> bindEventHandlerProperty(property, context)); + elementListeners.forEachProperty((property, name) -> { + Computation computation = bindEventHandlerProperty(property, + context); + + // Run eagerly to add initial listeners before element is attached + computation.recompute(); + }); return elementListeners.addPropertyAddListener( event -> bindEventHandlerProperty(event.getProperty(), context)); } - private void bindEventHandlerProperty(MapProperty eventHandlerProperty, - BindingContext context) { + private Computation bindEventHandlerProperty( + MapProperty eventHandlerProperty, BindingContext context) { String name = eventHandlerProperty.getName(); assert !context.listenerBindings.has(name); @@ -1181,6 +1186,7 @@ private void bindEventHandlerProperty(MapProperty eventHandlerProperty, context.listenerBindings.set(name, computation); + return computation; } private void removeEventHandler(String eventType, BindingContext context) { diff --git a/flow-tests/test-root-context/src/main/java/com/vaadin/flow/uitest/ui/DomListenerOnAttachView.java b/flow-tests/test-root-context/src/main/java/com/vaadin/flow/uitest/ui/DomListenerOnAttachView.java new file mode 100644 index 00000000000..154f164ab9b --- /dev/null +++ b/flow-tests/test-root-context/src/main/java/com/vaadin/flow/uitest/ui/DomListenerOnAttachView.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2019 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.uitest.ui; + +import com.vaadin.flow.component.dependency.HtmlImport; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.dom.Element; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.uitest.servlet.ViewTestLayout; + +@Route(value = "com.vaadin.flow.uitest.ui.DomListenerOnAttachView", layout = ViewTestLayout.class) +@HtmlImport("frontend://com/vaadin/flow/uitest/ui/DomListenerOnAttach.html") +public class DomListenerOnAttachView extends AbstractDivView { + public DomListenerOnAttachView() { + Div status = new Div(); + status.setText("Waiting for event"); + status.setId("status"); + + Element element = new Element("event-on-attach"); + element.addEventListener("attach", event -> { + status.setText("Event received"); + }); + + getElement().appendChild(element, status.getElement()); + } +} diff --git a/flow-tests/test-root-context/src/main/webapp/frontend/com/vaadin/flow/uitest/ui/DomListenerOnAttach.html b/flow-tests/test-root-context/src/main/webapp/frontend/com/vaadin/flow/uitest/ui/DomListenerOnAttach.html new file mode 100644 index 00000000000..33d18f9e7e1 --- /dev/null +++ b/flow-tests/test-root-context/src/main/webapp/frontend/com/vaadin/flow/uitest/ui/DomListenerOnAttach.html @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/DomListenerOnAttachIT.java b/flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/DomListenerOnAttachIT.java new file mode 100644 index 00000000000..b0756e606cd --- /dev/null +++ b/flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/DomListenerOnAttachIT.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2018 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.uitest.ui; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; + +import com.vaadin.flow.testutil.ChromeBrowserTest; + +public class DomListenerOnAttachIT extends ChromeBrowserTest { + + @Test + public void filtering() { + open(); + + String status = findElement(By.id("status")).getText(); + Assert.assertEquals("Event received", status); + } +}