Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DOM listeners before attaching the element #5195

Merged
merged 1 commit into from
Mar 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand All @@ -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 <code>dom-repeat</code> element.
Expand All @@ -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 <code>dom-repeat</code> element is in the DOM then
// this method should not be executed anymore. The logic below will replace
Expand All @@ -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; i<props.length; i++){
Expand All @@ -352,7 +352,7 @@ private native void hookUpPolymerElement(StateNode node, Element element)
if( currentPropsItem && currentPropsItem.nodeId ){
var nodeId = currentPropsItem.nodeId;
var value = currentPropsItem[propertyName];

// this is an attempt to find the template element
// which is not available as a context in the protype method
var host = this.__dataHost;
Expand All @@ -363,7 +363,7 @@ private native void hookUpPolymerElement(StateNode node, Element element)
while( !host.localName || host.__dataHost ){
host = host.__dataHost;
}

$entry(function () {
@SimpleElementBindingStrategy::handleListItemPropertyChange(*)(nodeId, host, propertyName, value, tree);
})();
Expand All @@ -374,7 +374,7 @@ private native void hookUpPolymerElement(StateNode node, Element element)
};
}
};

// dom-repeat doesn't have to be in DOM even if template has it
// such situation happens if there is dom-if e.g. which evaluates to <code>false</code> initially.
// in this case dom-repeat is not yet in the DOM tree until dom-if becomes <code>true</code>
Expand All @@ -389,7 +389,7 @@ private native void hookUpPolymerElement(StateNode node, Element element)
element.addEventListener('dom-change',replaceDomRepeatPropertyChange);
}
}

}-*/;

private static void handleListItemPropertyChange(double nodeId,
Expand Down Expand Up @@ -1153,16 +1153,21 @@ private void remove(JsArray<EventRemover> 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);

Expand All @@ -1181,6 +1186,7 @@ private void bindEventHandlerProperty(MapProperty eventHandlerProperty,

context.listenerBindings.set(name, computation);

return computation;
}

private void removeEventHandler(String eventType, BindingContext context) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!--
~ 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.
-->
<!-- Using an absolute URL is a bad practice, but the nesting depth here makes it incovenient traverse up with ../.. -->
<link rel="import" href="/frontend/bower_components/polymer/polymer-element.html">

<dom-module id="event-on-attach">
<template>
Fires an event when attached
</template>
<script>
class EventOnAttach extends Polymer.Element {
static get is() { return 'event-on-attach' }

connectedCallback() {
super.connectedCallback();

this.dispatchEvent(new CustomEvent('attach'));
}
}
customElements.define(EventOnAttach.is, EventOnAttach);
</script>
</dom-module>
Original file line number Diff line number Diff line change
@@ -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);
}
}