Skip to content

Commit

Permalink
Merge pull request #12 from vaadin-miki/11-grid-constructor
Browse files Browse the repository at this point in the history
#11 done
  • Loading branch information
vaadin-miki committed May 5, 2020
2 parents 1b0fdee + a8e4956 commit 863c36d
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 6 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# SuperTemplate

This is an extension of Vaadin 14.X `PolymerTemplate` class. It enables server-side access to properties defined in the template file, which is normally not possible.
This is an extension of Vaadin 14.X `PolymerTemplate` class. It enables server-side access to properties defined in the template file, which is normally not possible. It also attempts to solve a few general issues with templates.

## Limitations

Expand All @@ -19,7 +19,7 @@ Maven dependency:
<dependency>
<groupId>org.vaadin.miki</groupId>
<artifactId>super-template</artifactId>
<version>0.1.0</version>
<version>0.2.0</version>
</dependency>
```

Expand Down Expand Up @@ -77,10 +77,11 @@ For each attribute:

## Default behaviour

Unless changed, after setting each field according to its attributes, the object will go through extra configuration. This is defined by `TemplateFieldConfigurator` and by default three of those are available:
Unless changed, after setting each field according to its attributes, the object will go through extra configuration. This is defined by `TemplateFieldConfigurator` and by default those are available:
* if the value implements `HasText`, its `setText` method will be called with the text found in the element;
* if the value is an `Icon`, its server-side `Icon` will be changed to reflect the one specified in the element;
* if the value is a `Button` and the element has an icon, the icon will be set on the server side.
* if the value is a `Button` and the element has an icon, the icon will be set on the server side;
* if the value is a `Grid` and it is declared in the file as `Grid<BeanType>`, the field will be configured as if `new Grid<>(BeanType.class)` was called.

The default configurators can be skipped by:
* passing a `false` flag to the `SuperTemplate` constructor - for that particular template only;
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>org.vaadin.miki</groupId>
<artifactId>super-template</artifactId>
<version>0.2-SNAPSHOT</version>
<version>0.2.0</version>

<name>Super Template</name>
<description>An extension of PolymerTemplate that reads properties from the template and makes them available on the server side. Requires Vaadin 14.X.</description>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.vaadin.miki.supertemplate;

import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.polymertemplate.PolymerTemplate;
import com.vaadin.flow.data.binder.BeanPropertySet;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;

/**
* Configures bean type of a field of type {@link Grid}.
* @author miki
* @since 2020-05-05
*/
public class GridBeanTypeConfigurator implements TemplateFieldConfigurator {

private static final Logger LOGGER = LoggerFactory.getLogger(GridBeanTypeConfigurator.class);

@Override
public void configureFieldValue(Field field, Object value, PolymerTemplate<?> template, Element element) {
if(value instanceof Grid) {
try {
Class<?> dataType = (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
LOGGER.info("Discovered field {} to be of type Grid<{}>", field.getName(), dataType.getName());

Field beanTypeField = Grid.class.getDeclaredField("beanType");
if(beanTypeField.trySetAccessible())
beanTypeField.set(value, dataType);

Field propertySetField = Grid.class.getDeclaredField("propertySet");
propertySetField.setAccessible(true);
propertySetField.set(value, BeanPropertySet.get(dataType));
}
catch(ClassCastException cce) {
LOGGER.info("Could not discover bean type for field {}. Please make it Grid<YourDataType>.", field.getName());
} catch (IllegalAccessException | NoSuchFieldException e) {
LOGGER.warn("Could not access Grid.beanType and Grid.propertySet. Field {} will not work properly.", field.getName());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,17 @@ private TemplateFieldConfigurators() {} // instances not allowed
// buttons require extra processing, they may have an icon
public static final TemplateFieldConfigurator UPDATE_BUTTON_ICON = new UpdateButtonIconConfigurator();

/**
* Updates a grid to have a bean type, if declared in the Java class through generics.
*/
public static final TemplateFieldConfigurator GRID_BEAN_TYPE = new GridBeanTypeConfigurator();

/**
* Contains all of the {@link TemplateFieldConfigurator}s defined as {@code public static final} fields in this class.
* This array can be modified and it will affect all templates.
*/
public static final Collection<TemplateFieldConfigurator> DEFAULT_CONFIGURATORS = new ArrayList<>(Arrays.asList(
SET_TEXT, CREATE_STANDALONE_ICON, UPDATE_BUTTON_ICON
SET_TEXT, CREATE_STANDALONE_ICON, UPDATE_BUTTON_ICON, GRID_BEAN_TYPE
));

}
32 changes: 32 additions & 0 deletions src/test/java/org/vaadin/miki/supertemplate/Dummy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.vaadin.miki.supertemplate;

import java.util.Objects;

/**
* A dummy data type.
*/
public class Dummy {

private String contents;

public String getContents() {
return contents;
}

public void setContents(String contents) {
this.contents = contents;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Dummy dummy = (Dummy) o;
return Objects.equals(getContents(), dummy.getContents());
}

@Override
public int hashCode() {
return Objects.hash(getContents());
}
}
14 changes: 14 additions & 0 deletions src/test/java/org/vaadin/miki/supertemplate/SuperTemplateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.github.mvysny.kaributesting.v10.MockNpmTemplateParser;
import com.github.mvysny.kaributesting.v10.MockVaadin;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.textfield.TextField;
import org.junit.After;
Expand Down Expand Up @@ -47,6 +48,10 @@ public void testSuperViewHasPropertiesFromTemplate() {
Assert.assertNotNull(span);
Assert.assertEquals("a-span", span.getId().orElse(null));
Assert.assertEquals("World", span.getText());
Grid<Dummy> grid = superView.getGrid();
Assert.assertNotNull(grid);
Assert.assertSame(Dummy.class, grid.getBeanType());
Assert.assertNotNull(grid.addColumn("contents")); // adding columns should work
}

@Test
Expand All @@ -59,4 +64,13 @@ public void testVaadinViewDoesNotHavePropertiesFromTemplate() {
Assert.assertFalse(vaadinView.getSpan().getId().isPresent());
}

@Test(expected = UnsupportedOperationException.class)
public void testVaadinViewDoesNotHaveProperGrid() {
VaadinView vaadinView = new VaadinView();
Assert.assertNotNull(vaadinView);
Assert.assertNotNull(vaadinView.getGrid());
Assert.assertNull(vaadinView.getGrid().getBeanType());
vaadinView.getGrid().addColumn("contents");
}

}
8 changes: 8 additions & 0 deletions src/test/java/org/vaadin/miki/supertemplate/TestView.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.polymertemplate.Id;
import com.vaadin.flow.component.textfield.TextField;
Expand All @@ -17,6 +18,9 @@ public class TestView extends SuperTemplate<TestView.TestModel> {
@Id("a-span")
private Span span;

@Id("a-grid")
private Grid<Dummy> grid;

TextField getTextField() {
return textField;
}
Expand All @@ -25,6 +29,10 @@ Span getSpan() {
return span;
}

Grid<Dummy> getGrid() {
return grid;
}

public interface TestModel extends TemplateModel {} // nothing here

}
8 changes: 8 additions & 0 deletions src/test/java/org/vaadin/miki/supertemplate/VaadinView.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.polymertemplate.Id;
import com.vaadin.flow.component.polymertemplate.PolymerTemplate;
Expand All @@ -18,6 +19,9 @@ public class VaadinView extends PolymerTemplate<TestView.TestModel> {
@Id("a-span")
private Span span;

@Id("a-grid")
private Grid<Dummy> grid;

TextField getTextField() {
return textField;
}
Expand All @@ -26,6 +30,10 @@ Span getSpan() {
return span;
}

Grid<Dummy> getGrid() {
return grid;
}

public interface TestModel extends TemplateModel {} // nothing here

}
1 change: 1 addition & 0 deletions src/test/resources/test-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class TestView extends PolymerElement {
</style>
<vaadin-text-field id="a-text-field" placeholder="Hello" style="width: 100%;"></vaadin-text-field>
<span id="a-span">World</span>
<vaadin-grid id="a-grid"></vaadin-grid>
`;
}

Expand Down

0 comments on commit 863c36d

Please sign in to comment.