Polymer + Dart

Polymer.dart

The future of web development

+NicolasFrancois / @nicofrancois
+GuillaumeGirou / @GirouGuillaume

Web components

Web Components

Custom Element

Html Import

Template

Shadow Dom

Vanilla JS Web Component


<template>
    <p>Hello World!</p>
</template>
<script>(function() {
    var thisDoc = document.currentScript.ownerDocument;

    var element = Object.create(HTMLElement.prototype);
    element.createdCallback = function() {
        var template = thisDoc.querySelector('template').content;
        // TEMPLATE
        var clone = document.importNode(template, true);
        // SHADOW DOM
        this.createShadowRoot().appendChild(clone);
    };
    // CUSTOM ELEMENT
    document.registerElement('hello-world', { prototype: element });
})();</script>

Vanilla JS Web Component


<html>
    <head>
        
        <link rel="import" href="hello-world.html">
    </head>

    <body>
        
        <hello-world></hello-world>
    </body>
</html>

Polymer

Polymer

Polyfills

2014

webcomponents.js

Browser Support 2014 Browser Support Polyfills

Polymer.js

Sugaring

Polymer's material design elements

paper-tab 1 paper-tab 2 paper-tab 3
paper-button raised button


Toggle batman
core-toolbar

First Custom Element

Register custom element


<polymer-element name="hello-world">
  <template>
    <p>Hello {{name}}!</p>
  </template>
  <script>
    Polymer({
      name: 'World'
    });
  </script>
</polymer-element>
            

Dart

Dart

Language

  • Structured
  • Flexible
  • Improve maintainability of web applications
  • Open Source
  • Ecma Standard 408

Platform

  • Client and server
  • Virtuals Machines
  • Dependency manager
  • Javascript transpiler
  • IDE plugins

Samples


main() {
  var name = "World";
  print("Hello $name");
}
            

class Point {
  int x, y;
  
  Point(this.x, this.y);
  Point.zero() : x = 0, y = 0;
  
  String toString() => "x: $x, y: $y";
}
            

First Custom Element

Register custom element


<!-- import polymer-element's definition -->
<link rel="import" href="../../packages/polymer/polymer.html">

<polymer-element name="hello-world" noscript>
  <template>
    <p>Hello World!</p>
  </template>
</polymer-element>
            

Use custom element


<html>
  <head>
    <!-- import the hello-world -->
    <link rel="import" href="packages/dart/hello_world.html">
  </head>
  <body>
    <!-- use hello-world element -->
    <hello-world></hello-world>

    <!-- bootstrap polymer -->
    <script type="application/dart">export 'package:polymer/init.dart';</script>
  </body>
</html>
            

Bindings

Data binding


<link rel="import" href="../../packages/polymer/polymer.html">

<polymer-element name="hello-world">
  <template>
    <label>What is your name?</label>

    <input type="input" value="{{yourName}}"><!-- TWO-WAY DATA BINDING -->

    <p>Hello {{yourName}}!</p><!-- ONE-WAY DATA BINDING -->
  </template>
  <script type="application/dart" src="hello_world.dart"></script>
</polymer-element>
            

Data binding


import 'package:polymer/polymer.dart';

@CustomTag('hello-world')
class HelloWorld extends PolymerElement {
  @observable String yourName;

  HelloWorld.created() : super.created();
}
            

Custom attribute


import 'package:polymer/polymer.dart';

@CustomTag('hello-world')
class HelloWorld extends PolymerElement {
  @published String yourName;

  HelloWorld.created() : super.created();
}
            

                <hello-world yourName="John"></hello-world>
            

Conditional template


<template if="{{number % 2 == 0}}">{{number}} is even</template>
<template if="{{number % 2 != 0}}">{{number}} is odd</template>
            

@CustomTag('even-or-odd')
class EvenOrOdd extends PolymerElement {
  @observable int number = 0;
  // ...
}
            

Loop template


<ul>
  <template repeat="{{friend in friends}}">
    <li>Hello {{friend}}!</li>
  </template>
</ul>
            

@CustomTag('hello-friends')
class HelloFriends extends PolymerElement {
  List<String> friends = ['John Doe', 'Jane Doe', 'Mister X'];
  // ...
}
            

Filter


{{number | toHex | toUpperCase}}
            

@CustomTag('hex-number')
class HexNumber extends PolymerElement {
  String toHex(int number) => number.toRadixString(16);
  String toUpperCase(String s) => s.toUpperCase();
  // ...
}
            

Events

Handle event


<button on-click="{{increment}}"> Click me: {{count}}</button>
            

@CustomTag('click-counter')
class ClickCounter extends PolymerElement {
  @observable int count = 0;

  increment() => count++;
  // ...
}
            

Custom event


@CustomTag('click-counter')
class ClickCounter extends PolymerElement {
  @observable int count = 0;

  increment() => dispatchEvent(new CustomEvent('count', detail: ++count)); 
  // ...
}
            

<click-counter on-count="{{countHandler}}"></click-counter>      
            

@CustomTag('other-element')
class OtherElement extends PolymerElement {
  countHandler(Event e, int count, Element target) => print(count);
  // ...
}
            

Compose elements

Insertion point


<polymer-element name="post-card" noscript>
  <template>
    <div>
      <content select="img"></content>
      <content select="h2"></content>
    </div>
    <content></content>
  </template>
</polymer-element>
            

<post-card>
  <img src="img/avatar.png">
  <h2>Crazy Developer</h2>
  <p>Feels like the future!</p>
</post-card>
            

Crazy Developer

Feels like the future!

Extending other elements


<polymer-element name="click-counter" extends="button" on-click="{{increment}}">
    <template>Click me: {{count}}</template>
    <script type="application/dart" src="click_counter.dart"></script>
</polymer-element>
            

@CustomTag('click-counter')
class ClickCounter extends ButtonElement with Polymer, Observable {
  ClickCounter.created() : super.created() {
    polymerCreated();
  }

  @observable int count = 0;

  increment() => count++;
}
            

<button is="click-counter"></button>
            

Styling elements

:host


<polymer-element name="post-card" noscript>
  <template>
    <style>
      :host {
        background-color: #FFE25F;
      }
    </style>
    <div>
      <content select="img"></content>
      <content select="h2"></content>
    </div>
    <content></content>
  </template>
</polymer-element>
            

<post-card>...</post-card>
            

Crazy Developer

Feels like the future!

:host(.red)


<polymer-element name="post-card" noscript>
  <template>
    <style>
      :host(.red) {
        background-color: #BF3030;
      }
    </style>
    
    ...
  </template>
</polymer-element>
            

<post-card class="red">...</post-card>
            

Crazy Developer

Feels like the future!

shadow


<style>
  post-card.green::shadow * {
    background-color: #86B32D;
  }
</style>
<post-card class="green">...</post-card>
            

<polymer-element name="post-card" noscript>
  <template>
    <div>
      <content select="img"></content>
      <content select="h2"></content>
    </div>
    <content></content>
  </template>
</polymer-element>
            

Crazy Developer

Feels like the future!

deep


<style>
  post-card.blue /deep/ * {
    background-color: #009999;
  }
</style>
<post-card class="blue">...</post-card>
            

<polymer-element name="post-card" noscript>
  <template>
    <div>
      <content select="img"></content>
      <content select="h2"></content>
    </div>
    <content></content>
  </template>
</polymer-element>
            

Crazy Developer

Feels like the future!

Dart vs Javascript

  • Readability
  • IDE
  • Modularity
  • Performance

<thank-you>

dartlangfr.net/conferences/2014-10-28/

BY +NicolasFrancois / @nicofrancois
AND +GuillaumeGirou / @GirouGuillaume

Dart gplus.to/dartlangfr