Skip to content

Commit

Permalink
fix: check if each.item is already evaluated
Browse files Browse the repository at this point in the history
  • Loading branch information
jorenrui committed Feb 16, 2024
1 parent e04b4d9 commit c535282
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 22 deletions.
67 changes: 53 additions & 14 deletions lib/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,35 @@ export class Entity {
return eachEl != null
}

getEachEl() {
return this.getClosestEl(':each')
}

getEachItemEl() {
const eachItemEl = this.element.hasAttribute(':each.item')
? this.element
: this.getClosestEl(':each.item')
return eachItemEl
}

isInsideEachItem() {
if (this.element.hasAttribute(':each')) return false

const eachItemEl = this.getEachItemEl()
return !(eachItemEl == null || eachItemEl?.[':each.item'])
}

isEachItem() {
return this.element.hasAttribute(':each.item')
}

isEachItemEvaluated() {
return (
this.element.getAttribute(':each.item') === 'true' ||
this.getClosestEl(':each.item')?.[':each.item'] === 'true'
)
}

getClosestEl(attr) {
attr = attr.replaceAll(':', '\\:').replaceAll('.', '\\.')

Expand Down Expand Up @@ -213,24 +242,34 @@ export class Entity {
try {
const entity = new Entity(element)

if (entity.isInsideEachEl()) {
const closestEachItem = entity.element.hasAttribute(':each.item')
? entity
: entity.getClosestEl(':each.item')

const isEachItemInitialized =
closestEachItem === this.element ||
closestEachItem?.contains(this.element)

if (!isEachItemInitialized) continue
entity.dispose()
}

entity.init()
const eachEl = entity.getEachEl()
const eachItemEl = entity.getEachItemEl()
const isEachItemAndInitialized =
eachEl != null && eachItemEl != null && eachEl.contains(eachItemEl)

if (
eachEl == null ||
eachEl === entity.element ||
isEachItemAndInitialized
)
entity.init()
else entity.dispose()
} catch (error) {
console.error('Failed to initialize child entity:', error)
}
}

const eachItemEls = [...this.element.querySelectorAll('*[\\:each\\.item]')]
if (this.isEachItem()) eachItemEls.push(this.element)

eachItemEls.forEach((el) => {
el.setAttribute(':each.item', true)

Object.entries(el.dataset).forEach(([key, value]) => {
if (!key.startsWith('mini.each:')) return
delete el.dataset[key]
})
})
}

dispose() {
Expand Down
13 changes: 5 additions & 8 deletions lib/entity/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,23 +88,20 @@ export class Attributes {
}

evaluateEachItem() {
if (this.base.element.hasAttribute(':each')) return

const eachItemEl = this.base.element.hasAttribute(':each.item')
? this.base.element
: this.base.getClosestEl(':each.item')
if (eachItemEl == null) return
if (!this.base.isInsideEachItem()) return
if (this.base.isEachItemEvaluated()) return

const state = {}

const eachItemEl = this.base.getEachItemEl()

Object.entries(eachItemEl.dataset).forEach(([key, value]) => {
if (!key.startsWith('mini.each:')) return

const name = key.replace('mini.each:', '')

try {
this.base.state[name] = JSON.parse(value)
this.base.element.removeAttribute(key)
} catch (error) {
console.error(
`Failed to parse dataset.${key} for Entity#${this.base.id}:`,
Expand Down Expand Up @@ -223,7 +220,7 @@ export class Attributes {

items.forEach((item, index) => {
Array.from(this.childClone).forEach((child) => {
child.setAttribute(':each.item', true)
child.setAttribute(':each.item', false)
child.dataset[`mini.each:${variable}`] = JSON.stringify(item)
if (indexName) child.dataset[`mini.each:${indexName}`] = index

Expand Down

0 comments on commit c535282

Please sign in to comment.