Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/components/cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,18 @@ export default class IgcGridLiteCell<T extends object> extends LitElement {
} as unknown as IgcCellContext<T>;
}

private get _shouldAdoptStyles(): boolean {
return this.adoptRootStyles && this.cellTemplate != null;
}

public override connectedCallback(): void {
super.connectedCallback();
this._adoptedStylesController.shouldAdoptStyles(this._shouldAdoptStyles);
}

protected override update(props: PropertyValues<this>): void {
if (props.has('adoptRootStyles')) {
this._adoptedStylesController.shouldAdoptStyles(
this.adoptRootStyles && this.cellTemplate != null
);
this._adoptedStylesController.shouldAdoptStyles(this._shouldAdoptStyles);
}

super.update(props);
Expand Down
66 changes: 66 additions & 0 deletions test/adopt-root-styles.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,4 +478,70 @@ describe('Grid adopt-root-styles property', () => {
expect(computedStyle.fontWeight).to.equal('700');
});
});

describe('Virtualizer cell caching', () => {
beforeEach(async () => {
adoptRootStylesTDD.columnConfig = [
{
field: 'name',
sortable: true,
cellTemplate: (ctx: IgcCellContext<TestData>) =>
litHtml`<div class="custom-cell-class">${ctx.value}</div>`,
},
{ field: 'id', sortable: true },
];
await adoptRootStylesTDD.setUp();
});

afterEach(() => adoptRootStylesTDD.tearDown());

it('should preserve adopted styles when a cell is disconnected and reconnected by the virtualizer', async () => {
const cell = adoptRootStylesTDD.rows.first.cells.get('name');
const cellElement = cell.element as IgcGridLiteCell<TestData>;

// Verify initial adopted state
// @ts-expect-error - Accessing private controller for testing
expect(cellElement._adoptedStylesController.hasAdoptedStyles).to.be.true;

// Simulate virtualizer caching: disconnect the cell and reconnect it with
// properties already set (no Lit property-change cycle will fire in update)
const parentNode = cellElement.parentNode!;
parentNode.removeChild(cellElement);
await nextFrame();
parentNode.appendChild(cellElement);
await cellElement.updateComplete;

// connectedCallback must re-apply shouldAdoptStyles regardless of whether
// adoptRootStyles changed, because the property did not change so the
// update() guard (props.has('adoptRootStyles')) never fires
// @ts-expect-error - Accessing private controller for testing
expect(cellElement._adoptedStylesController.hasAdoptedStyles).to.be.true;

const customDiv = cellElement.shadowRoot!.querySelector('.custom-cell-class');
expect(customDiv).to.exist;
const computedStyle = window.getComputedStyle(customDiv!);
expect(computedStyle.color).to.equal('rgb(255, 0, 0)');
});

it('should preserve adopted styles after sorting already-sorted data across multiple columns', async () => {
// The test data IDs are 1–8 in ascending order, so sorting ascending by id
// produces no reordering. The virtualizer therefore recycles cells in-place
// without a full connected/disconnected lifecycle, meaning connectedCallback
// is never re-invoked and update()'s props.has('adoptRootStyles') guard
// does not fire — this is the exact scenario the connectedCallback fix covers.
await adoptRootStylesTDD.sortHeader('id');

// A second sort column keeps the order stable (all ids are unique, so the
// secondary key never kicks in), producing another no-op reorder pass.
await adoptRootStylesTDD.sortHeader('name');

for (let i = 0; i < adoptRootStylesTDD.grid.rows.length; i++) {
const cellElement = adoptRootStylesTDD.rows.get(i).cells.get('name')
.element as IgcGridLiteCell<TestData>;

// @ts-expect-error - Accessing private controller for testing
expect(cellElement._adoptedStylesController.hasAdoptedStyles).to.be.true;
}
});
});
});
Loading