24
Web Components & GWT Introducing GWT-Polymer Manuel Carrasco Moñino. GWT-meetup 2015

Introducing GWT Polymer (vaadin)

Embed Size (px)

Citation preview

Page 1: Introducing GWT Polymer (vaadin)

Web Components & GWT Introducing GWT-Polymer

Manuel Carrasco Moñino.GWT-meetup 2015

Page 2: Introducing GWT Polymer (vaadin)

Provide a Java API to consume Vaadin Components in GWT

Motivation

Page 3: Introducing GWT Polymer (vaadin)

Web Components:State of the art

Page 4: Introducing GWT Polymer (vaadin)

State of the Art

Page 5: Introducing GWT Polymer (vaadin)

Native browser support

Page 6: Introducing GWT Polymer (vaadin)

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

Page 7: Introducing GWT Polymer (vaadin)

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

Page 8: Introducing GWT Polymer (vaadin)

Vaadin Components

A collection of the awesome Vaadin widget set. vaadin components

○ grid

Page 9: Introducing GWT Polymer (vaadin)

GWT & Web Components

Page 10: Introducing GWT Polymer (vaadin)

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

Page 11: Introducing GWT Polymer (vaadin)

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

Page 12: Introducing GWT Polymer (vaadin)

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);}

Page 13: Introducing GWT Polymer (vaadin)

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); }}

Page 14: Introducing GWT Polymer (vaadin)

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();

}

Page 15: Introducing GWT Polymer (vaadin)

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);

Page 16: Introducing GWT Polymer (vaadin)

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); }}

Page 17: Introducing GWT Polymer (vaadin)

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);

Page 18: Introducing GWT Polymer (vaadin)

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>

Page 19: Introducing GWT Polymer (vaadin)

Introducing GWT-Polymer

Page 20: Introducing GWT Polymer (vaadin)

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

Page 21: Introducing GWT Polymer (vaadin)

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).

Page 22: Introducing GWT Polymer (vaadin)

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

Page 23: Introducing GWT Polymer (vaadin)

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.