diff --git a/src/component/Component.ts b/src/component/Component.ts index 0da718c..f5e9d9e 100644 --- a/src/component/Component.ts +++ b/src/component/Component.ts @@ -93,9 +93,6 @@ export abstract class Component { createElements (): Element[] { // TODO: [C] - for ( const detachable of this.rerenderSubscriptions_ ) { - detachable.detach(); - } let renderables = this.render.call(this.instanceProxy); @@ -125,6 +122,8 @@ export abstract class Component { throw new Error('cannot re-render a component with zero elements'); } + this.onWillDetachFromDOM_(); + // The reference element lets us know where to put new elements const referenceElement = this.elements_[0]; @@ -141,6 +140,24 @@ export abstract class Component { }) } + notifyWillDetachFromDOM () { + this.onWillDetachFromDOM_(); + } + onWillDetachFromDOM_ () { + // Detach rerender subscriptions + for ( const detachable of this.rerenderSubscriptions_ ) { + detachable.detach(); + } + + // Detach listeners from child renderables generated last time + if ( ! this.renderChildren_ ) { + throw new Error('tried to detach before rendering'); + } + for ( const renderable of this.renderChildren_ ) { + renderable.notifyWillDetachFromDOM(); + } + } + createDynamicVAO_ (vaoName: string, value?: any) { // TODO: [E], [I] this.vaos_[vaoName] = new ScalarVAO(value ?? null); diff --git a/src/component/Tag.ts b/src/component/Tag.ts index b752028..0c25f5c 100644 --- a/src/component/Tag.ts +++ b/src/component/Tag.ts @@ -61,6 +61,12 @@ export class Tag { return [el]; } + notifyWillDetachFromDOM() { + for ( const axiom of this.axioms_ ) { + axiom.detach(); + } + } + notifyMounted (event: INotifyMounted) { console.log('notifyMounted called on a tag', this); if ( this.element_ == null ) { diff --git a/src/component/componentdefs.ts b/src/component/componentdefs.ts index d4e7f97..17712b5 100644 --- a/src/component/componentdefs.ts +++ b/src/component/componentdefs.ts @@ -6,6 +6,7 @@ export interface INotifyMounted { export interface Renderable { createElements: () => Element[] + notifyWillDetachFromDOM: () => void notifyMounted: (event: INotifyMounted) => void } export interface RenderableConstructor {