VitalyT
VitalyT

Reputation: 1701

Create Html Tree view with native javascript / HTML

I need to create an HTML/CSS tree view as in the example from already created object using native javascript.

Please suggest,

BR

Upvotes: 0

Views: 2696

Answers (1)

Nenad Vracar
Nenad Vracar

Reputation: 122145

You could first build nested structure and then use recursive approach to also create html from that data where if the current element has children property you call the function again with that children array as a data parameter.

var data = [{"name":"container-1","type":"container","description":"container description"},{"name":"category-1","type":"category","parent":"container-1"},{"name":"grid-1","type":"grid","parent":"category-1"},{"name":"chart-1","type":"chart","parent":"category-1"},{"name":"container-2","type":"container"},{"name":"category-2","type":"category","parent":"container-2"},{"name":"category-3","type":"category","parent":"container-2"},{"name":"grid-2","type":"grid","parent":"category-2"},{"name":"chart-2","type":"chart","parent":"category-2"},{"name":"grid-3","type":"grid","parent":"category-3"}]

function toTree(data, pid = undefined) {
  return data.reduce((r, e) => {
    if (pid == e.parent) {
      const obj = { ...e }
      const children = toTree(data, e.name)
      if (children.length) obj.children = children;
      r.push(obj)
    }

    return r
  }, [])
}

function toHtml(data, isRoot = true) {
  const ul = document.createElement('ul')

  if (!isRoot) {
    ul.classList.add('hide')
  }

  data.forEach(e => {
    let isVisible = isRoot;
    const li = document.createElement('li')
    const text = document.createElement('span')
    const button = document.createElement('button')

    if (e.children) {
      button.textContent = '+'
      li.appendChild(button)
    }

    text.textContent = e.name
    li.appendChild(text)

    if (e.children) {
      const children = toHtml(e.children, false)
      li.appendChild(children)

      button.addEventListener('click', function() {
        if (isRoot) {
          isVisible = !isVisible
        }

        button.textContent = isVisible ? '+' : '-'
        children.classList.toggle('hide')

        if (!isRoot) {
          isVisible = !isVisible
        }
      })
    }

    ul.appendChild(li)

  })

  return ul;
}

const tree = toTree(data)
const html = toHtml(tree)

document.body.appendChild(html)
.hide {
   display: none;
}

button {
  margin-right: 10px;
}

Upvotes: 3

Related Questions