Introducing GWT Polymer (vaadin)

Post on 26-Jul-2015

1,173 views 12 download

transcript

Web Components & GWT Introducing GWT-Polymer

Manuel Carrasco Moñino.GWT-meetup 2015

Provide a Java API to consume Vaadin Components in GWT

Motivation

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.