Eric / Brooklyn

Random 5

Whitespace Problems

Ruby Exits

Appending in Javascript

Sendgrid Ban

Clean URLs

Multi-tab Websockets

Honeypot Bots

Bad Content

JS Data Chutzpah

Concerns

Cookies

Stripe and Tap

Emoji Bits

Git

Ruby vs. Ruby

Extending Devise

Rails UJS

ENV Variables

Web Accounts

See All

Appending in Javascript

Jan 2021

Things we can append

  1. Text — Hello
  2. HTML, as text — <div>Hello</div>
  3. HTML, as Node Elements — created in JS via document.createElement('div')

Some Tools

  • innerHTML
  • append
  • appendChild
  • insertAdjacentHTML

A Scenario

Let’s say we have a buddy list in a chat application.

When Tiffany comes online, we want to append her to your buddy list.

Let’s assume that you receive a data object when this happens;

data = {
	name: 'tiffany',
	status: 'online',
	...
}

And you want to use this data object to append the relevant HTML to the DOM inside the buddy list.

<ul id="buddies">
	<li><a>Rabbi</a></li>
	<li><a>Maneki</a></li>
	<li><a>Baxter</a></li>
	<li><a>Shadow</a></li>
	<!-- Put Tiffany here -->
</ul>

innerHTML

This is probably the worst option of the bunch. We’d have to do something like:

const new_buddy = `<li><a>${data.name}</a></li>`

const list = document.querySelector('#buddies')
list.innerHTML += new_buddy

Initially, this seems to work.

Our new buddy list will look like:

<ul id="buddies">
	<li><a>Rabbi</a></li>
	<li><a>Maneki</a></li>
	<li><a>Baxter</a></li>
	<li><a>Shadow</a></li>
	<li><a>Tiffany</a></li>
</ul>

However, this is a bad option because we will lose any existing event listeners inside of #buddies.

We lose event listeners because of the nature of +=.

A += B behaves the same as A = A + B.

Instead of appending, we’re actually replacing.

And since our a tags above have click events, this is a big problem.

append

First, if you need to support Internet Explorer, you are out of luck and should skip to the next section.

append allows us to append Node objects or text. It might appear as though this would work:

const new_buddy = "	<li><a>Tiffany</a></li>"

const list = document.querySelector('#buddies')
list.append(new_buddy)

However, this doesn’t work, because append will treat new_buddy as text and not HTML. In our browser, we’ll see HTML text instead of rendered HTML.

To append HTML, we have to feed in Node objects.

const new_buddy = document.createElement('li')
const new_link = document.createElement('a')
new_link.innerHTML = data.name
new_buddy.innerHTML = new_link

const list = document.querySelector('#buddies')
list.append(new_buddy)

Note that there’s also a prepend if we’d like.

appendChild

appendChild only takes in Node objects, so we can basically do the same thing as we did in append.

const new_buddy = document.createElement('li')
const new_link = document.createElement('a')
new_link.innerHTML = data.name
new_buddy.innerHTML = new_link

const list = document.querySelector('#buddies')
list.appendChild(new_buddy)

Note that this will work in Internet Explorer (unlike append).

Also worth reminding that we cannot use appendChild with text.

insertAdjacentHTML

insertAdjacentHTML will take in text, and parse as HTML.

const new_buddy = `<li><a>${data.name}</a></li>`

const list = document.querySelector('#buddies')
list.insertAdjacentHTML('beforeend', new_buddy)

In addition to beforeend, we could have specified ‌beforebegin, ‌afterbegin, or ‌afterend.

Winners and Losers

innerHTML is a loser as it’ll break our site.

append works well if you like the flexibility of working with Node elements or text, and don’t need to support Internet Explorer.

appendChild works well if you like working with Node elements.

insertAdjacentHTML is nice if you like generating HTML via text, and having greater control over placement.