Skip to content

Commit

Permalink
Read text for template element (#9008)
Browse files Browse the repository at this point in the history
* Read text content as an attribute data

* Add unit tests for template element set text

* Add IT for template element set text

* Update IT after change for reading text

* Improve code a bit based on review

* Add missed tag for the component

* Remove extra symbol

* Add lost lines after merge
# Conflicts:
#	flow-server/src/main/java/com/vaadin/flow/component/polymertemplate/IdCollector.java
  • Loading branch information
Denis authored and pleku committed Feb 2, 2021
1 parent 9f37d6b commit 89a1374
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.jsoup.nodes.Element;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.template.internal.AbstractInjectableElementInitializer;
import com.vaadin.flow.internal.AnnotationReader;

/**
Expand Down Expand Up @@ -136,8 +137,10 @@ private boolean collectElementData(String id, Field field) {
Optional<String> tagName = element
.map(org.jsoup.nodes.Element::tagName);
if (element.isPresent()) {
Element domElement = element.get();
tagById.put(id, tagName.get());
fetchAttributes(id, element.get().attributes());
fetchAttributes(id, domElement.attributes());
setText(id, domElement);
}

return element.isPresent();
Expand Down Expand Up @@ -177,13 +180,12 @@ private void fetchAttributes(String id, Attributes attributes) {
if (attributes.size() == 0) {
return;
}
HashMap<String, String> attrs = new HashMap<>();
attributes.forEach(attr -> setAttributeData(attr, attrs));
attributesById.put(id, attrs);
Map<String, String> data = getAttributeData(id);
attributes.forEach(attr -> setAttributeData(attr, data));
}

private void setAttributeData(Attribute attribute,
HashMap<String, String> data) {
Map<String, String> data) {
if (isBooleanAttribute(attribute)) {
data.put(attribute.getKey(), Boolean.TRUE.toString());
} else {
Expand All @@ -194,4 +196,18 @@ private void setAttributeData(Attribute attribute,
private boolean isBooleanAttribute(Attribute attribute) {
return attribute.getKey().equals(attribute.toString());
}

private Map<String, String> getAttributeData(String id) {
return attributesById.computeIfAbsent(id, key -> new HashMap<>());
}

private void setText(String id, Element domElement) {
if (domElement.children().isEmpty()) {
// the text can be set only if element has no any child except a
// text node
getAttributeData(id).put(
AbstractInjectableElementInitializer.TEXT_DATA,
domElement.ownText());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@
public abstract class AbstractInjectableElementInitializer
implements Consumer<Map<String, String>> {

/**
* Represents text key which should be set to an {@link Element} via
* {@link Element#setText(String)}.
* <p>
* The real attribute may not contain {@code "="} sign in the name so it's
* safe to use this special key for text value in a map.
*/
public static final String TEXT_DATA = "=text";

private final Element element;

private static final Map<String, ElementInitializationStrategy> INIT_STRATEGIES = createStategies();
Expand Down Expand Up @@ -131,6 +140,8 @@ private static Map<String, ElementInitializationStrategy> createStategies() {
result.put("translate", attributeStrategy);

result.put("disabled", new DisabledInitializationStrategy());

result.put(TEXT_DATA, new TextInitializationStrategy());
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2000-2020 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.component.template.internal;

import java.io.Serializable;

import com.vaadin.flow.dom.Element;

/**
* Initializes Element via setting a text value.
*
* @author Vaadin Ltd
* @since
*
*/
class TextInitializationStrategy
implements ElementInitializationStrategy, Serializable {

@Override
public void initialize(Element element, String name, String value) {
element.setText(value);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasStyle;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.template.internal.AbstractInjectableElementInitializer;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.dom.ElementFactory;

Expand Down Expand Up @@ -113,6 +114,13 @@ public void initializeElement_disabled_elementIsDisabled() {
Assert.assertFalse(element.isEnabled());
}

public void initializeElement_setText_textIsSet() {
initializer.accept(Collections.singletonMap(
AbstractInjectableElementInitializer.TEXT_DATA, "foo bar"));

Assert.assertEquals("foo bar", element.getText());
}

@Tag(Tag.DIV)
public static class TestComponent extends Component implements HasStyle {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,29 @@ public DisabledElementTemplate(VaadinService service) {
VaadinService service) {
super(parser, service);
}
}

@Tag("foo-bar")
private static class ElementWithTextLitTemplate extends LitTemplate {

@Id("labelId")
private com.vaadin.flow.dom.Element label;

@Id("hasHierarchy")
private com.vaadin.flow.dom.Element div;

public ElementWithTextLitTemplate(VaadinService service) {
this((clazz, tag, svc) -> new LitTemplateParser.TemplateData("",
Jsoup.parse("<dom-module id='" + tag
+ "'><label id='labelId'>foo bar</label>"
+ "<div id='hasHierarchy'>baz <a>foo</a> bar</div></dom-module>")),
service);
}

ElementWithTextLitTemplate(LitTemplateParser parser,
VaadinService service) {
super(parser, service);
}

}

Expand Down Expand Up @@ -119,4 +142,19 @@ public void attachExistingElementWithAttributeValue_elementIsDisabled() {
Assert.assertFalse(template.label.isEnabled());
}

public void attachExistingElementWithoutChidlrenWithText_elementHasText() {
ElementWithTextLitTemplate template = new ElementWithTextLitTemplate(
service);

Assert.assertEquals("foo bar", template.label.getText());
}

@Test
public void attachExistingElementWithChidlrenWithText_elementHasNoText() {
ElementWithTextLitTemplate template = new ElementWithTextLitTemplate(
service);

Assert.assertEquals("", template.div.getText());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasStyle;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.template.internal.AbstractInjectableElementInitializer;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.dom.ElementFactory;

Expand Down Expand Up @@ -121,6 +122,13 @@ public void initializeElement_disabled_elementIsDisabled() {
Assert.assertFalse(element.isEnabled());
}

public void initializeElement_setText_textIsSet() {
initializer.accept(Collections.singletonMap(
AbstractInjectableElementInitializer.TEXT_DATA, "foo bar"));

Assert.assertEquals("foo bar", element.getText());
}

@Tag(Tag.DIV)
public static class TestComponent extends Component implements HasStyle {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,28 @@ public DisabledElementTemplate() {
DisabledElementTemplate(TemplateParser parser) {
super(parser);
}
}

@Tag(TAG)
private static class ElementWithTextTemplate
extends PolymerTemplate<ModelClass> {

@Id("labelId")
private com.vaadin.flow.dom.Element label;

@Id("hasHierarchy")
private com.vaadin.flow.dom.Element div;

public ElementWithTextTemplate() {
this((clazz, tag, service) -> new TemplateData("",
Jsoup.parse("<dom-module id='" + tag
+ "'><label id='labelId'>foo bar</label>"
+ "<div id='hasHierarchy'>baz <a>foo</a> bar</div></dom-module>")));
}

ElementWithTextTemplate(TemplateParser parser) {
super(parser);
}

}

Expand Down Expand Up @@ -825,6 +847,19 @@ public void attachExistingElementWithAttributeValue_elementIsDisabled() {
Assert.assertFalse(template.label.isEnabled());
}

public void attachExistingElementWithoutChidlrenWithText_elementHasText() {
ElementWithTextTemplate template = new ElementWithTextTemplate();

Assert.assertEquals("foo bar", template.label.getText());
}

@Test
public void attachExistingElementWithChidlrenWithText_elementHasNoText() {
ElementWithTextTemplate template = new ElementWithTextTemplate();

Assert.assertEquals("", template.div.getText());
}

@Test
public void attachExistingElement_injectedByIDdChild_onlyOneElementIsCreated() {
TemplateInjectTemplate template = new TemplateInjectTemplate();
Expand Down
2 changes: 2 additions & 0 deletions flow-tests/test-root-context/frontend/AttributeTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class AttributeTemplate extends PolymerElement {
<div style="padding: 10px; border: 1px solid black">
<div id="div" title="foo" foo="bar" baz></div>
<div id="disabled" disabled></div>
<div id="hasText">foo</div>
<div id="hasTextAndChild">foo <label>bar</label> baz</div>
</div>
<slot>
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export class AttributeLitTemplate extends LitElement {
<div style="padding: 10px; border: 1px solid black">
<div id="div" title="foo" foo="bar" baz></div>
<div id="disabled" disabled></div>
<div id="hasText">foo</div>
<div id="hasTextAndChild">foo <label>bar</label> baz</div>
</div>
<slot>
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ public class LitTemplateAttributeView extends LitTemplate
@Id("disabled")
private Div disabledDiv;

@Id("hasText")
private Div hasText;

@Id("hasTextAndChild")
private Div hasTextAndChild;

@Override
protected void onAttach(AttachEvent attachEvent) {
setId("template");
Expand All @@ -36,5 +42,10 @@ protected void onAttach(AttachEvent attachEvent) {
div.setId("disabledInfo");
div.setText("Enabled: " + disabledDiv.isEnabled());
add(div);

div = new Div();
div.setText(hasText.getText() + " " + hasTextAndChild.getText() + "|");
div.setId("text-info");
add(div);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,13 @@ public ChildOrderView() {

addChildToContainer2.addClickListener(event -> {
Element text = Element.createText("\nServer text "
+ (containerWithText.getElement().getChildCount() + 1));
+ (containerWithText.getElement().getChildCount()));
containerWithText.getElement().appendChild(text);
});

prependChildToContainer2.addClickListener(event -> {
Element text = Element.createText("\nServer text "
+ (containerWithText.getElement().getChildCount() + 1));
+ (containerWithText.getElement().getChildCount()));
containerWithText.getElement().insertChild(0, text);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public class TemplateAttributeView extends PolymerTemplate<TemplateModel>

@Id("disabled")
private Div disabledDiv;
@Id("hasText")
private Div hasText;

@Id("hasTextAndChild")
private Div hasTextAndChild;

@Override
protected void onAttach(AttachEvent attachEvent) {
Expand All @@ -37,5 +42,10 @@ protected void onAttach(AttachEvent attachEvent) {
div.setId("disabledInfo");
div.setText("Enabled: " + disabledDiv.isEnabled());
add(div);

div = new Div();
div.setText(hasText.getText() + " " + hasTextAndChild.getText() + "|");
div.setId("text-info");
add(div);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -165,29 +165,28 @@ public void prependTextsFromServer_textsAreAddedBeforeExistingOnes() {
assertNodeOrder(container, "Client text");

clickAndWaitForContainerToChange(container, "prependChildToContainer2");
assertNodeOrder(container, "Client text", "Server text 1");
assertNodeOrder(container, "Server text 1Client text");

clickAndWaitForContainerToChange(container, "prependChildToContainer2");
assertNodeOrder(container, "Client text", "Server text 2",
"Server text 1");
assertNodeOrder(container, "Server text 2", "Server text 1Client text");

clickAndWaitForContainerToChange(container,
"addClientSideChildToContainer2");
assertNodeOrder(container, "Client text", "Server text 2",
"Server text 1", "Client text");
assertNodeOrder(container, "Server text 2", "Server text 1Client text",
"Client text");

clickAndWaitForContainerToChange(container, "prependChildToContainer2");
assertNodeOrder(container, "Client text", "Server text 3",
"Server text 2", "Server text 1", "Client text");
assertNodeOrder(container, "Server text 3", "Server text 2",
"Server text 1Client text", "Client text");

clickAndWaitForContainerToChange(container,
"removeChildFromContainer2");
assertNodeOrder(container, "Client text", "Server text 3",
"Server text 2", "Client text");
assertNodeOrder(container, "Server text 3", "Server text 2",
"Server text 1", "Client text");

clickAndWaitForContainerToChange(container,
"removeChildFromContainer2");
assertNodeOrder(container, "Client text", "Server text 3",
assertNodeOrder(container, "Server text 3", "Server text 2",
"Client text");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,9 @@ public void readTemplateAttribiute() {
TestBenchElement isDisabled = template.$(TestBenchElement.class)
.id("disabledInfo");
Assert.assertEquals("Enabled: false", isDisabled.getText());

TestBenchElement textInfo = template.$(TestBenchElement.class)
.id("text-info");
Assert.assertEquals("foo |", textInfo.getText());
}
}

0 comments on commit 89a1374

Please sign in to comment.