When checking on the checkbox i’m trying to create the div boxes and when unchecking remove it dynamically.
I know with React i could do this in 2min but i’m trying to learn Vanilla JS way
Current issues i’m having:
- When checking on checkbox it renders more elements than one
- When unchecking checkbox for example all one element is still rendered.
END GOAL: dynamically add and remove Div boxes depending on what is in state
variable, (console.log
that its outputting should give guidance on how correctly it should look) but also making sure no extra boxes are being used / rendered.
window.onload = () => { const checkbox = document.querySelectorAll('.checkbox') let state = [] for (idx of checkbox) { idx.addEventListener('change', (e) => { if (e.currentTarget.checked === true) { state.push(e.currentTarget.id) renderOnDom(state, 'add', e.currentTarget.id) // Experimenting } if (e.currentTarget.checked === false) { state = state.filter((item) => item !== e.currentTarget.id) renderOnDom(state, 'remove', e.currentTarget.id) // Experimenting } console.log('state', state) }) } } const renderOnDom = (el, option, id) => { if (option === 'add') { el.map((item, idx) => { const div = document.createElement('div') div.setAttribute('key', item) div.className = 'test' div.innerHTML = `Box ${item}` document.querySelector('#projects').appendChild(div) }) } if (option === 'remove') { const test = document.querySelectorAll('.test') const prod = document.querySelector('#projects') for (const iterator of test) { if (iterator.attributes.key.value === id) { prod.removeChild(prod.firstChild) } } } }
<input id="id1" data="name1" class="checkbox" type="checkbox" /> <label for="id1">Test 1</label> <input id="id2" data="name2" class="checkbox" type="checkbox" /> <label for="id2">Test 2</label> <input id="id3" data="name3" class="checkbox" type="checkbox" /> <label for="id3">Test 3</label> <div id="projects"></div>
Advertisement
Answer
Hey I have updated your snippet to do what I think you want to do.
In a nutshell, the source of truth is state
array. So after any changes to it, reset the dom using resetDom()
and then fire renderOnDom()
.
window.onload = () => { const checkbox = document.querySelectorAll('.checkbox') let state = [] for (idx of checkbox) { idx.addEventListener('change', (e) => { if (e.currentTarget.checked === true) { state.push(e.currentTarget.id) } if (e.currentTarget.checked === false) { state = state.filter((item) => item !== e.currentTarget.id) } renderOnDom(state, e.currentTarget.id) }) } } const resetDom = () => { const projects = document.querySelector("#projects"); while (projects.firstChild) { projects.removeChild(projects.firstChild) } } const renderOnDom = (el, id) => { resetDom(); el.forEach((item, idx) => { const div = document.createElement('div') div.setAttribute('key', item) div.className = 'test' div.innerHTML = `Box ${item}` document.querySelector('#projects').appendChild(div) }) }
<input id="id1" data="name1" class="checkbox" type="checkbox" /> <label for="id1">Test 1</label> <input id="id2" data="name2" class="checkbox" type="checkbox" /> <label for="id2">Test 2</label> <input id="id3" data="name3" class="checkbox" type="checkbox" /> <label for="id3">Test 3</label> <div id="projects"></div>