diff --git a/lib/entity.js b/lib/entity.js index 03f6853..34dcd10 100644 --- a/lib/entity.js +++ b/lib/entity.js @@ -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('.', '\\.') @@ -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() { diff --git a/lib/entity/attributes.js b/lib/entity/attributes.js index 1fcd0ac..64eebc5 100644 --- a/lib/entity/attributes.js +++ b/lib/entity/attributes.js @@ -88,15 +88,13 @@ 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 @@ -104,7 +102,6 @@ export class Attributes { 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}:`, @@ -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