Skip to content

Commit

Permalink
fix: remove items in o-for
Browse files Browse the repository at this point in the history
  • Loading branch information
sebkolind committed Nov 16, 2023
1 parent 8fd3b1d commit b7e7186
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 15 deletions.
7 changes: 3 additions & 4 deletions example/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const Component = new O('[hello-world]', function () {
text: 'Click me',
items: [
{ title: 'Item 1' },
{ title: 'Item 2' }
{ title: 'Item 2' },
{ title: 'Item 3' }
]
})
})
Expand All @@ -22,9 +23,7 @@ const Button = new O('button', function () {
count,
text: `Clicked ${count}`,
items: [
{ title: 'Item 1' },
{ title: 'Item 2' },
{ title: 'Item 3' }
{ title: 'Item 1' }
]
})
})
Expand Down
2 changes: 1 addition & 1 deletion example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<span o-text="name"></span>
<button o-text="text"></button>
<div>
Clicked <span o-text="count"></span> times
Clicked <span o-text="count">0</span> times
</div>
</div>
<script type="module" src="app.js"></script>
Expand Down
39 changes: 29 additions & 10 deletions lib/one.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const TEXT = 'o-text'
const FOR = 'o-for'
const KEY = 'key'

class O {
#el = null
Expand Down Expand Up @@ -55,32 +57,49 @@ class O {

render (target, state = this.#state) {
const iterator = target.length ? target : [target]

for (const el of iterator) {
if (el.getAttribute(TEXT)) {
const text = el.getAttribute(TEXT)
const key = el.getAttribute('key')
const key = el.getAttribute(KEY)
const s = key ? state?.[key]?.[text] : state[text]
el.textContent = s != null
? s
: el.textContent

if (s != null && s !== el.textContent) {
el.textContent = s
}
}
if (el.getAttribute('o-for')) {

if (el.getAttribute(FOR)) {
const template = el.children[0].cloneNode(true)
const array = state[el.getAttribute('o-for')]
// TODO: Handle if the array length is less than,
// the current children length, which means we have to remove
const rendered = template.getAttribute(KEY)
const array = state[el.getAttribute(FOR)]

// Remove all children that are not in the array
if (rendered) {
const children = Array.from(el.children)

let i = 0
for (const c of children) {
if (!array[i]) {
el.removeChild(c)
}
i++
}
}

// Only remove first child if it is the template
if (!template.getAttribute('key')) {
if (!rendered) {
el.children[0].remove()
}

array.forEach((item, i) => {
// Don't append already existing children
if (!el.children[i]) {
template.setAttribute('key', i)
template.setAttribute(KEY, i)
el.append(template.cloneNode(true))
}
})

this.render(el.children, array)
}

Expand Down

0 comments on commit b7e7186

Please sign in to comment.