Web Components With Rails

Preview:

Citation preview

Web Components and Rails

Boris Nadion boris@astrails.com

@borisnadion

@borisnadion http://astrails.com

awesome web and mobile appssince 2005

1997

bank

Active DesktopMicrosoft

desktop widgets

tasks management appvanilla javascript + HTML running in IE4 on a desktop

innovation

mostly C/C++ until 2005

Ruby

Rails

bin

There are only 10 types of people in world: those who understand binary and those who don’t.

102types of people in web development

backend

frontend

html

html + css

html + css + javascript

full stack112

testwhat engineer are you?

2 recent memory leakswhat did they blow?

server

2 backend

server browser

2 backend

2 frontend

server browser

2 backend

2 frontend

1 1 full stack

server browser

2 backend

2 frontend

1 1 full stack

designer/PM

2005

prototype.js + effects.js

$(…) with $$(…)$$ lookup is much more expensive than $

jQuery2006

Angular.js

ember.js

Backbone/Marionette

MVC / MVVM / MV*

class  MyApp.SomeController  extends  Marionette.Controller      show:  (id)  -­‐>          App.mainRegion.show  new  MyApp.SomeView(              model:  App.request("somemodel:load",  id)          )  

class  MyApp.SomeView  extends  Marionette.ItemView      template:  "templates/some/show"      templateHelpers:  -­‐>          klass:  =>  if  @model.has_something()  then  "some"  else  "nothing"      initialize:  =>          @listenTo  @model,  "change",  @render  

class  Models.SomeModel  extends  Backbone.Model      url:  -­‐>          Routes.somemodel_path(@get("id"))  

App.reqres.setHandlers      "some  model:load":  (id)  -­‐>          res  =  new  Model.SomeModel(id:  id)          res.fetch()          res

document.registerElement

XFoo  =  document.registerElement('x-­‐foo')  document.body.appendChild(new  XFoo())

proto  =  Object.create(HTMLElement.prototype)  document.registerElement(‘x-­‐foo’,  prototype:  proto)

lifecycle callbacks

proto  =  Object.create(HTMLElement.prototype)  

proto.createdCallback  =  -­‐>  #...  proto.attachedCallback  =  -­‐>  #...  proto.detachedCallback  =  -­‐>  #...  proto.attributeChangedCallback  =  (name,  from,  to)  -­‐>  #...  

XFoo  =  document.registerElement('x-­‐foo',  prototype:proto)

encapsulate functionality

proto.createdCallback  =  -­‐>      @addEventListener  'click',  (e)  -­‐>          alert('yeah')

photo.createdCallback  =  -­‐>      @innerHTML  =  "<b>I'm  bold  and  inside  the  x-­‐foo</b>"

Shadow Root

proto.createdCallback  =  -­‐>      shadow  =  @createShadowRoot()      shadow.innerHTML  =  "<b>I'm  bold  and  inside  the  shadow  root</b>"

Templates

proto.createdCallback  =  -­‐>      template  =  document.querySelector('#mytemplate')      clone  =  document.importNode(template.content,  true)      @createShadowRoot().appendChild(clone)  

<template  id="mytemplate">      <style>          p  {  color:  yellow;  }      </style>      <p>I'm  yellow  in  a  shadow  root</p>  </template>

Polymerhttps://www.polymer-project.org/

<!-­‐-­‐  Define  element  -­‐-­‐>  <polymer-­‐element  name="my-­‐counter"  attributes="counter">      <template>          <style>  /*...*/  </style>          <div  id="label"><content></content></div>          Value:  <span  id="counterVal">{{counter}}</span><br>          <button  on-­‐tap="{{increment}}">Increment</button>      </template>      <script>          Polymer({              counter:  0,  //  Default  value              counterChanged:  function()  {                  this.$.counterVal.classList.add('highlight');              },              increment:  function()  {                  this.counter++;              }          });      </script>  </polymer-­‐element>  

<!-­‐-­‐  Use  element  -­‐-­‐>  <my-­‐counter  counter="10">Points</my-­‐counter>

X-Tagshttp://x-tags.org/

xtag.register  "x-­‐accordion",      extends:  "div"      lifecycle:          created:  -­‐>          inserted:  -­‐>          removed:  -­‐>          attributeChanged:  -­‐>      events:          "click:delegate(x-­‐toggler)":  -­‐>      accessors:          togglers:              get:  -­‐>              set:  (value)  -­‐>      methods:          nextToggler:  -­‐>          previousToggler:  -­‐>

Bosonichttp://bosonic.github.io/

<element  name="b-­‐hello-­‐world">          <style>                  </style>          <template>                  <h3>Hello,  world!</h3>                  <p>Lorem  ipsum</p>          </template>          <script>                  ({                          createdCallback:  function()  {                                  var  root  =  this.createShadowRoot();                                root.appendChild(this.template.content.cloneNode(true));                          }                  });          </script>  </element>

Brickhttp://mozbrick.github.io/

Polymerhttps://www.polymer-project.org/

polyfillsupport old browsers

<!-­‐-­‐  Polyfill  Web  Components  support  for  older  browsers  -­‐-­‐>  <script  src="components/platform/platform.js"></script>  

<!-­‐-­‐  Import  element  -­‐-­‐>  <link  rel="import"  href="google-­‐map.html">  

<!-­‐-­‐  Use  element  -­‐-­‐>  <google-­‐map  lat="37.790"  long="-­‐122.390"></google-­‐map>

lightweight CEShttps://github.com/WebReflection/document-register-element

• custom elements • html imports • templates • shadow root

Polymer Railshttps://github.com/alchapone/polymer-rails

//  application.html  //=  require  polymer/polymer  //=  require  my-­‐navigation/my-­‐navigation  

//  my-­‐navigation.html.erb  <polymer-­‐element  name="my-­‐navigation">      <template>          <%=  stylesheet_link_tag  'my-­‐navigation/style'%>          <ul  class="navigation">              <li><a  href="/">Home</a></li>              <li><a  href="/">Contacts</a></li>              <li><a  href="/">Blog</a></li>              <li><a  href="/">Twitter</a></li>              <li><a  href="/">Facebook</a></li>          </ul>      </template>  

<%=  javascript_include_tag  "my-­‐navigation/my-­‐navigation"%>  </polymer-­‐element>  

//  my-­‐navigation.coffee  Polymer  'my-­‐navigation'  

//  style.sass  \:host      display:  block  

.navigation      list-­‐style:  none      margin:  0      background:  #fff  #  ...

Should I use Polymer for my next project?https://news.ycombinator.com/item?id=7970781

encapsulation

clean up HTML

hide everythingshadow DOM

HTML vs. MV*

frontend is cool again

thanks!

Boris Nadion astrails.com/blog

Recommended