diff --git a/packages/angular-table/src/flex-render.ts b/packages/angular-table/src/flex-render.ts index 3799538104..90ae1d0a03 100644 --- a/packages/angular-table/src/flex-render.ts +++ b/packages/angular-table/src/flex-render.ts @@ -1,9 +1,9 @@ +import type { EffectRef } from '@angular/core' import { ChangeDetectorRef, Directive, DoCheck, effect, - type EffectRef, Inject, inject, Injector, @@ -15,21 +15,27 @@ import { Type, ViewContainerRef, } from '@angular/core' +import type { + CellContext, + HeaderContext, + Table, + TableFeatures, +} from '@tanstack/table-core' +import { memo } from '@tanstack/table-core' import { FlexRenderComponentProps } from './flex-render/context' import { FlexRenderFlags } from './flex-render/flags' import { - flexRenderComponent, FlexRenderComponent, + flexRenderComponent, } from './flex-render/flex-render-component' import { FlexRenderComponentFactory } from './flex-render/flex-render-component-ref' +import type { FlexRenderTypedContent } from './flex-render/view' import { FlexRenderComponentView, FlexRenderTemplateView, - type FlexRenderTypedContent, FlexRenderView, mapToFlexRenderTypedContent, } from './flex-render/view' -import { memo } from '@tanstack/table-core' export { injectFlexRenderContext, @@ -51,7 +57,12 @@ export type FlexRenderContent> = standalone: true, providers: [FlexRenderComponentFactory], }) -export class FlexRenderDirective> +export class FlexRenderDirective< + TProps extends + | NonNullable + | CellContext + | HeaderContext, + > implements OnChanges, DoCheck { readonly #flexRenderComponentFactory = inject(FlexRenderComponentFactory) @@ -68,9 +79,13 @@ export class FlexRenderDirective> @Input({ required: true, alias: 'flexRenderProps' }) props: TProps = {} as TProps + @Input({ required: false, alias: 'flexRenderNotifier' }) + notifier: 'doCheck' | 'tableChange' = 'tableChange' + @Input({ required: false, alias: 'flexRenderInjector' }) injector: Injector = inject(Injector) + table: Table renderFlags = FlexRenderFlags.ViewFirstRender renderView: FlexRenderView | null = null @@ -97,7 +112,9 @@ export class FlexRenderDirective> ngOnChanges(changes: SimpleChanges) { if (changes['props']) { + this.table = 'table' in this.props ? this.props.table : null this.renderFlags |= FlexRenderFlags.PropsReferenceChanged + this.bindTableDirtyCheck() } if (changes['content']) { this.renderFlags |= @@ -114,8 +131,13 @@ export class FlexRenderDirective> return } - this.renderFlags |= FlexRenderFlags.DirtyCheck + if (this.notifier === 'doCheck') { + this.renderFlags |= FlexRenderFlags.DirtyCheck + this.doCheck() + } + } + private doCheck() { const latestContent = this.#getContentValue() if (latestContent.kind === 'null' || !this.renderView) { this.renderFlags |= FlexRenderFlags.ContentChanged @@ -129,6 +151,28 @@ export class FlexRenderDirective> this.update() } + #tableChangeEffect: EffectRef | null = null + + private bindTableDirtyCheck() { + this.#tableChangeEffect?.destroy() + this.#tableChangeEffect = null + let firstCheck = !!(this.renderFlags & FlexRenderFlags.ViewFirstRender) + if (this.table && this.notifier === 'tableChange') { + this.#tableChangeEffect = effect( + () => { + this.table.get() + if (firstCheck) { + firstCheck = false + return + } + this.renderFlags |= FlexRenderFlags.DirtyCheck + this.doCheck() + }, + { injector: this.injector, forceRoot: true }, + ) + } + } + update() { if ( this.renderFlags & diff --git a/packages/angular-table/src/injectTable.ts b/packages/angular-table/src/injectTable.ts index a6eed63239..be794fe81a 100644 --- a/packages/angular-table/src/injectTable.ts +++ b/packages/angular-table/src/injectTable.ts @@ -76,7 +76,6 @@ export function injectTable< table._setRootNotifier(tableSignal as any) - // proxify Table instance to provide ability for consumer to listen to any table state changes - return table as any + return table }) }