0

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

Please suggest,

BR

2
  • you asked the same question today. Commented Apr 13, 2020 at 16:19
  • So do you have an answer , for generating the html tree :) ? Commented Apr 13, 2020 at 16:33

1 Answer 1

3

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;
}

Sign up to request clarification or add additional context in comments.

2 Comments

thanks @Nenad Vracar , but i need it with +/- , means when press + it expands the relevant node. Same for - , minimize the content. As in the 1st picture
You can try const obj = Object.assign({}, e) instead

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.