introducing gwt polymer (vaadin)
TRANSCRIPT
Web Components & GWT Introducing GWT-Polymer
Manuel Carrasco Moñino.GWT-meetup 2015
Web Components:State of the art
State of the Art
Native browser support
PolymerPolymer makes it easier and faster to create anything from a button to a complete application across desktop, mobile, and beyond.
● webcomponents.js● polymer.js● core-components
○ collapse○ drawer○ dropdown○ field○ header○ icon○ input○ menu○ range○ splitter○ toolbar○ tooltip
Polymer Paper components
The Paper elements are a set of UI elements that implement the material design spec
paper components○ button○ checkbox○ dialog○ elements○ fab○ focusable○ icon○ input○ item○ progress○ radio○ ripple○ shadow○ slider○ tabs○ toast○ toggle
Vaadin Components
A collection of the awesome Vaadin widget set. vaadin components
○ grid
GWT & Web Components
1. Use JsInterop to wrap Js objects and export Java classesa. @JsType Wrap JS Objects without writing JSNIb. @JsExport Expose GWT classes and methods to JS (not used)c. @JsFunction Use interfaces as JS Functions (some issues)
2. Hand write Java Interfaces for the Web APIa. Window, Document, Element, Style, Events, …b. Implementation does not extend JSO, needs casting (issues)c. They might come with Elemental-2.0
3. Code generationa. There could be ways to create all the java boilerplate code
GWT JsInterop
1. Create reusable methods to import and create new instances of web components
2. Define a Java Interface per component and event- Extends HTMLElement or Event
3. Optionally Wrap each Interface in a Widget class for classic GWT apps.
How to consume WC
Interfaces for native JS objects@JsTypepublic interface HTMLElement extends Element {}
@JsTypepublic interface Element extends Node { @JsProperty String getInnerHTML();
@JsProperty DOMTokenList getClassList();
void setAttribute(String name, String value); String getAttribute(String name); void removeAttribute(String name);}
@JsTypepublic interface Node extends EventTarget {}
@JsTypepublic interface EventTarget { void addEventListener(String type, EventListener listener);}
Reusable methods public class Polymer { // Ensures that the tagName has been registered, otherwise injects // the appropriate <import> tag in the document header public static void ensureHTMLImport(String tagName) { if ( !registered(tagName)) { String href = GWT.getModuleBaseForStaticFiles() + "bower_components/" + tagName + "/" + tagName + ".html";
Element link = Document.get().createLinkElement(); link.setAttribute("rel", "import"); link.setAttribute("href", href); Document.get().getHead().appendChild(htmlImport); } } // Returns a new instance of the Element. It loads the webcomponent // if not loaded yet. public static <T> T createElement(String tagName) { ensureHTMLImport(tagName); return (T)Document.get().createElement(tagName); }}
The WC Element interface
@JsTypepublic interface PaperButton extends HTMLElement {
@JsProperty PaperButton setLabel(String val); @JsProperty String getLabel();
@JsProperty PaperButton setRaisedButton(boolean val); @JsProperty boolean getRaisedButton();
@JsProperty PaperButton setIcon(String val); @JsProperty String getIcon();
}
Consume WC in Java (Element API) // Create a new instance of PaperButton PaperButtonElement button = Polymer.create(PaperButtonElement.TAG;
// Set some properties button.icon("polymer") .label("Polymer") .raisedButton(false);
// Add event listeners button.addEventListener("click", new EventListener() { public void onBrowserEvent(Event event) { ... } });
// Append to the document myContainerElement.appendChild(button);
The WC Widget Classpublic class PaperButton extends PolymerWidget { //Default Constructor. public PaperButton() { this(""); } //Constructor used by UIBinder public PaperButton(String html) { this(PaperButtonElement.TAG, html); } // Used when this element is extended by another. protected PaperButton(String tag, String html) { super(tag, html); }
// Gets a handle to the Polymer object's underlying DOM element. public PaperButtonElement getPolymerElement() { return (PaperButtonElement) getElement(); } public boolean isRaised() { return getPolymerElement().isRaised(); }}
public class PolymerWidget extends HTMLPanel { public PolymerWidget(String tag, String html) { super(tag, html); Polymer.ensureHTMLImport(tag); }}
Consume WC in Java (Widget API)
// Widgets allow consume WC using the GWT classic way.PaperButton button = new PaperButton();
button.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { // ... }});
RootPanel.get().add(button);
Consume WC in UIBinder<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:p='urn:import:com.vaadin.components.gwt.polymer.client.widget'>
<ui:style> .container paper-button.colored { background: #4285f4; color: #fff; }</ui:style>
<g:HTMLPanel>
<p:PaperButton toggle="" raised="" active="" addStyleNames="{style.colored}">active</p:PaperButton>
<paper-button raised="" noink="">Click me</paper-button>
</g:HTMLPanel>
Introducing GWT-Polymer
GWT-Polymer 1. It’s a code generator to produce GWT wrappers for
polymer elementsa. Scrapes source documentation
2. Uses standard JS libraries to parse components.a. node.js, npm, bower, gulpb. context-free parser + lodash.template
3. It’s a Vaadin Labs projecta. Just released a paper gwt API snapshot (using polymer 0.5)b. Work in progress to support polymer 0.9 (hydrolysis parser)c. Still under definition, expect package name changes, etc
GWT-Polymer workflow1. Checkout git clone github.com/vaadin/gwt-polymer2. Run npm install3. Edit the bower.json file and add/remove the
components you need for your project.4. Run bower install to download components5. Run gulp gwt-api in order to generate all java files6. Run mvn clean package to produce your package .jar7. Everything is contained in the artefact (polyfill,
components, java code).
GWT-Polymer goals
1. Very little code to maintain.a. 950 LOC / 108 KB
2. But it produces a lot of java codea. 13400 LOC (paper & core elements)
3. It uses native JS parsers for JS code.a. The same tools that polymer usesb. No GWT generators nor APT processors.
4. Standard tools for web developers.a. They can deliver gwt libraries without knowing java
Discussion
1. Should we deliver separated ready-to-use libraries?a. GWT-Paper 0.5.6.x (matches paper version)b. Vaadin-Components 0.5.0.x (matches vaadin version)
2. Should we support GWT Widgets or Elements?3. Makes sense to use JS code generators, or should we
use the Java way?4. Could we eventually support other JS parsers to wrap
other JS libraries? a. closure annotations, typescript, etc.
Thanks
Links- gwt-polymer project- gwt-polymer-paper .jar artifact- gwt-polymer-paper demo