Skip to content

Instantly share code, notes, and snippets.

@collin
Last active September 2, 2016 20:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save collin/6fe60877a0f22d22159cb19acf0887c0 to your computer and use it in GitHub Desktop.
Save collin/6fe60877a0f22d22159cb19acf0887c0 to your computer and use it in GitHub Desktop.
Framework Agnostic Components

Yeah, that would be nice

We have some framework agnostic components. They work very well.

<a>, <p>, <script>, <input>, <svg>, even the dreaded <table>.

Imagine a nightmare scenario where <table> was implemented:

<table
  headers="myTableData.headers"
  rows="myTableData.rows"
/>

We live in this nightmare scenario.

var CoolTable = require('cool-table-constructor');
new CoolTable({
  element: document.querySelector('#my-cool-table'),
  headers: [{ /*...*/ }],
  rows: [{ /*...*/ }],
});

Framework agnostic components can not take references to data objects. For a component to be portable, it must be declarative and composable.

<cool-table>
  <cool-table-head>
    Row Header #1
  </cool-table-head>

  <cool-table-head>
    Row Header #2
  </cool-table-head>

  <cool-table-row>/* etc. and so on */</cool-table-row>
  <cool-table-row>/* etc. and so on */</cool-table-row>
  <cool-table-row>/* etc. and so on */</cool-table-row>
</cool-table

Any framework can manage those components.

Data flow is the problem. The solution for reusable components is to NOT solve it.

The implementation of <cool-table> can use some pretty amazing strategies to help keep its children under control no matter how you add/remove them.

1 : getElementsByTagName gives you an always up-to-date collection of elements by a tag name. It can be scoped to a parent element.

2: Event delegation, we don't have to manage all of our event handlers, just bind on the most logical parent element and delegate away.

class CoolTable extends HTMLElement {
  constructor () {
    this.headers = this.getElementsByTagName('cool-table-head');
    this.rows = this.getElementsByTagName('cool-table-row');
  }

  attachedCallback () {
    this.addEventListener('click', (event) => {
      if (event.target.matches('cool-table-head') {
       this.sortTable(event);
      }
    });
  }

  sortTable (event) {
    for (let row of this.rows) {
      /* real cool table sorting */  
    }
  }
}

customElements.define('coo-table', CoolTable);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment