JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1
  • Score
    100M100P100Q27731F
  • License ISC

hyperHTML + WebComponents

Package Exports

  • hyper-element

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (hyper-element) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

hyper-element

A combining the best of hyperHTML and Custom Elements!

npm version CDN link

Your new custom-elements are built with hyperHTML and will be re-rendered on attribute and store change.

Live Demo



Define a Custom Element

document.registerElement("my-elem", class extends hyperElement{

  render(Html){
    Html`hello ${this.attrs.who}`
  }

})

To use your element

<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/hyperhtml@latest/min.js"></script>
  <script src="https://unpkg.com/hyper-element@latest/source/bundle.js"></script>
</head>
<body>
  <my-elem who="world"></my-elem>
</body>
<html>

Output

<my-elem who="world">
    hello world
</my-elem>

Api

Define your element

There are 2 functions. render is required and setup is optional

render

This is what will be displayed with in your element. Use the Html to define your content

render(Html,store){

    Html`
      <h1>
          Lasted updated at ${new Date().toLocaleTimeString()}
      </h1>
    `
}

setup

The setup function wires up an external data-source

Connent a data source

Example to re-rendering when the mouse moves and pass current mouse values to render

// getMouseValues(){ ... }

setup(onNext){
    onMouseMove(onNext(getMouseValues))
}

re-rendering with out a data source

Example of re-rendering every second

setup(onNext){
    setInterval(onNext(), 1000);
}

Set initial values to pass to every render

Example of attach an object that will be used on evey render

setup(onNext){
    onNext({max_levels:3})
}

How to cleanup

Any logic you wish to run when the element is removed from the page should be returned as a function from the setup call

setup(onNext){
   const next = onNext(user);
   socket.addEventListener('message', next);
   const teardown = function(){
     socket.removeEventListener('message', next);
   }
   return teardown
}

Returning a "teardown function" from setup address the problem of needing a reference to the resource you what to release. If the "teardown function" was a public function. We would need to store the reference to the resource some, that the teardown can access it when call.

With this approach there is no leaking of references.

✎ To subscribe to 2 events

setup(onNext){

  const next = onNext(user);

  mobx.autorun(next);       // update when changed (real-time feedback)
  setInterval(next, 1000);  // update every second (update "the time is now ...")

}

this

  • this.attrs : the attributes on the tage <my-elem min="0" max="10" /> = { min:0, max:10 }
    • Attributes will be parsed to try and cast them to Javascript types
    • Casting types supported: Boolean & Number
  • this.store : the value returned from the store function. !only update before each render
  • this.wrapedContent : the text content embedded between your tag <my-elem>Hi!</my-elem> = "Hi!"

Templates

You can declare markup to be used as a template within the custom element

To enable templates

  1. Add an attribute "templates" to you custom element
  2. Define the template markup within your element
<my-list template data-json='[{"name":"ann","url":""},{"name":"bob","url":""}]' >
<div><a href="{url}">{name}</a></div>
</my-list>
document.registerElement("my-list",class extends hyperElement{

      render(Html){
        Html`
        ${this.attrs["data-json"].map(user => Html.template(user))}
        `
      }
 })

Output:

<my-list template data-json='[{"name":"ann","url":""},{"name":"bob","url":""}]' >
    <div>
      <a href="">ann</a>
    </div>
    <div>
      <a href="">bob</a>
    </div>
</my-list>

Render to string

You can use the innerShadow property to get the innerHTML of the shadow-dom

// create an element
const elem = document.createElement("profile-elem")
      elem.setAttribute('name', 'ashlyn');

// view hidden markup
console.log(elem,elem.innerShadow)

Example of connecting to a data store

backbone

var user = new (Backbone.Model.extend({
    defaults: {
        name: 'Guest User',
    }
}));


document.registerElement("my-profile", class extends hyperElement{

  setup(onNext){
    user.on("change",onNext(user.toJSON.bind(user)));
    // OR user.on("change",onNext(()=>user.toJSON()));
  }

  render(Html,{name}){
    Html`Profile: ${name}`
  }
})

mobx

const user = observable({
  name: 'Guest User'
})


document.registerElement("my-profile", class extends hyperElement{

  setup(onNext){
    mobx.autorun(onNext(user));
  }

  render(Html,{name}){
    Html`Profile: ${name}`
  }
})

redux

document.registerElement("my-profile", class extends hyperElement{

  setup(onNext){
    store.subcribe(onNext(store.getState)
  }

  render(Html,{user}){
    Html`Profile: ${user.name}`
  }
})