DEV Community

Ivan
Ivan

Posted on • Edited on

Easy apps with hyperHTML — 6, Customizing my custom elements

Part 6 written by Trevor Ganus,

pinguxx image
paritho image
  1. Introduction, wire/bind
  2. Events and components
  3. Moar about components and simple state management
  4. Wire types and custom definitions (intents)
  5. Custom elements with hyper
  6. Customizing my custom elements
  7. Testing!
  8. Async loading, placeholder and a Typeahead with hyper
  9. Handling routes
  10. 3rd party libraries

Recap

In parts 1–5, we talked about the basics of hyperHTML. We also learned about an amazing feature called hyper.Component. We dove into “intents ” that let us extend hyperHTML and simplify our templates. While learning all this we created a simple table:

Finally, we learned the basics of custom elements and a nice little utility called hyperHTML-Element, which gives us some of the hyper.Component features out of the box, and so much more.

In part 6, we’re going to discover how we can convert our table from a component to a custom element. We’ll also see how easy it is to add functionality to our custom element, extending it to be even more useful. Using custom elements makes it so easy to reuse our code, a baby could do it — if the baby knew HTML, and JavaScript, of course. Also, once we have a custom element, we don’t need hyperHTML anywhere else in our app unless we want it. This makes the custom elements plug-and-play with any framework. When was the last time a React component could say that?

Columns

Let’s start thinking about the elements of the table: header, footer and body. For our case, header and footer are the important parts. We will generate the footer based on the data just like before.

Let’s start with a custom element for the columns. This element will contain the information necessary to render:

  • the label (for the header)
  • the attribute used for this column (from the data)
  • if it’s sortable or not
  • the type of data to display

Simple right? We don’t even render anything, all the heavy lifting will be in the table itself.

Table

Now let’s generate a custom element with a simple table.

Let’s first add a hyper-column to our HTML

Then, we need to update our created function to read the columns and store them in an array that we can reuse later:

(used [].slice.call instead of […this.querySelectorAll(“hyper-column”)] because of an error using stackblitz)

And lastly, let’s update our template to use the columns.

Well cool. But we are not really using data from anywhere… let’s fix that. We’ll add a data property.

We now need to update our <tbody> part of the template to show one row for each item in the data.

(if wire(column, `col${item.id}`) looks unfamiliar to you, review part 4!)

Of course, we still need to pass data to the table. The index file is where we’ll do that.

Let’s see our full code so far:

To finish off the table, we need to add the rest of the columns. Notice, this is very similar to what we’ve done in previous parts of this tutorial!

Intents

Recall intents from part 4? Let’s use intents to display icons and dates correctly. We happen to like the octicon library of icons, but you can feel free to bring your own icon set.

Then extract the rendering of the <td>’s and <th>’s for easier reading.

(Note that, for user-provided values, you should be sure to use the ‘text’ type. Otherwise, use of ‘html’ could lead to potential HTML injection issues. Normally, hyperHTML will escape HTML used in expressions ${...}).

We are using state so let’s make sure we have a defaultState set:

And again update our template

Much easier to follow :D.

State & Events

We need to be able to sort the data when a user clicks on the table header. Let’s add onclick="${this}" data-call="headerClick" to our a tags so we can do this. We will also need to add the headerClick function to handle the event.

Remember calling setState will call render(), so we don’t need to explicitly call render() here. Let’s see our table with the sorting and icons working.

Footer

Then at the bottom of the table, we will add our footer.

Nothing fancy here. Aaannddd we are done… or at least we replicated the component we had with custom elements. This is no small thing. Now, we can just use <hyper-table> with some <hyper-column> inside and you have a simple yet functional table.

Customization

Every good table should be able to add/update/remove columns, right? Glad you asked! Let’s add some functions to our table that will allow us to do just that.

First let’s add to our column element a new attribute called name. This will be used to update/remove columns. If no name is passed we’ll just use the attribute.

addColumn

We will let the developer add a column by passing a new <hyper-column>. We’ll also allow an object to be passed with the attributes needed. This will update our columns array.

removeColumn

Based on the newly added name to the column, we can easily remove columns from the table. In theory we could use index instead of name, but I wanted to show that we can do either with the elements.

updateColumn

Again using the name attribute, we can update the column details.

Let’s see how it looks:

Well, that was easy, and we enhanced our table with very useful functionality!.

Now you are a custom element/hyperHTML master :D. Or, at least you can start creating your own elements! In the next part we are going to add testing to our table element and maybe add the ability to filter the table display. Please send us your feedback to improve this tutorial.


Top comments (0)