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
38 changes: 38 additions & 0 deletions projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { IgxColumnComponent, IgxGridComponent, IgxHierarchicalGridComponent } from 'igniteui-angular';
import { html } from 'lit-html';
import { firstValueFrom, fromEvent, skip, timer } from 'rxjs';
import { ComponentRefKey, IgcNgElement } from './custom-strategy';
import hgridData from '../assets/data/projects-hgrid.js';
Expand Down Expand Up @@ -52,6 +53,43 @@ describe('Elements: ', () => {
const columnComponent = (await columnEl.ngElementStrategy[ComponentRefKey]).instance as IgxColumnComponent;
expect(gridComponent.columnList.toArray()).toContain(columnComponent);
});

it(`should keep IgcNgElement instance in template of another IgcNgElement #15678`, async () => {
const gridEl = document.createElement("igc-grid");
testContainer.appendChild(gridEl);
const columnEl = document.createElement("igc-column") as IgcNgElement;
gridEl.appendChild(columnEl);
gridEl.primaryKey = 'id';
gridEl.data = [{ id: '1' }];
(gridEl as any).detailTemplate = (ctx) => {
return html`<div>
<igc-grid id="child${ctx.implicit.id}"></igc-grid>
</div>`;
}

// TODO: Better way to wait - potentially expose the queue or observable for update on the strategy
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 2));

// sigh (。﹏。*)
(gridEl as any).toggleRow('1');
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 2));

let detailGrid = document.querySelector<IgcNgElement>('#child1');
expect(detailGrid).toBeDefined();
let detailGridComponent = (await detailGrid?.ngElementStrategy[ComponentRefKey])?.instance as IgxGridComponent;
expect(detailGridComponent).toBeDefined();

// close and re-expand row detail:
(gridEl as any).toggleRow('1');
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 2));
(gridEl as any).toggleRow('1');
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 2));

detailGrid = document.querySelector<IgcNgElement>('#child1');
expect(detailGrid).toBeDefined();
detailGridComponent = (await detailGrid?.ngElementStrategy[ComponentRefKey])?.instance as IgxGridComponent;
expect(detailGridComponent).toBeDefined("Detail child grid was destroyed on re-expand");
});
});

describe('Grid integration scenarios.', () => {
Expand Down
19 changes: 18 additions & 1 deletion projects/igniteui-angular-elements/src/app/custom-strategy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ApplicationRef, ChangeDetectorRef, ComponentFactory, ComponentRef, Injector, OnChanges, QueryList, Type, ViewContainerRef, reflectComponentType } from '@angular/core';
import { ApplicationRef, ChangeDetectorRef, ComponentFactory, ComponentRef, DestroyRef, Injector, OnChanges, QueryList, Type, ViewContainerRef, reflectComponentType } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { NgElement } from '@angular/elements';
import { fromEvent } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
Expand Down Expand Up @@ -48,6 +49,14 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
return this._templateWrapper;
}

private _configSelectors: string;
public get configSelectors(): string {
if (!this._configSelectors) {
this._configSelectors = this.config.map(x => x.selector).join(',');
}
return this._configSelectors;
}

constructor(private _componentFactory: ComponentFactory<any>, private _injector: Injector, private config: ComponentConfig[]) {
super(_componentFactory, _injector);
}
Expand Down Expand Up @@ -233,6 +242,14 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
}
value = this.templateWrapper.addTemplate(value);
// TODO: discard oldValue

// check template for any angular-element components
this.templateWrapper.templateRendered.pipe(takeUntilDestroyed(componentRef.injector.get(DestroyRef))).subscribe((element) => {
element.querySelectorAll<IgcNgElement>(this.configSelectors)?.forEach((c) => {
// tie to angularParent lifecycle for cached scenarios like detailTemplate:
c.ngElementStrategy.angularParent = componentRef;
});
});
}
if (componentRef && componentConfig?.boolProps?.includes(property)) {
// bool coerce:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ChangeDetectorRef, Component, QueryList, TemplateRef, ViewChildren } from '@angular/core';
import { Subject } from 'rxjs';
import { TemplateRefWrapper } from './template-ref-wrapper';

import { render, TemplateResult } from 'lit-html';
Expand All @@ -14,6 +15,7 @@ type TemplateFunction = (arg: any) => TemplateResult;
export class TemplateWrapperComponent {

public templateFunctions: TemplateFunction[] = [];
public templateRendered = new Subject<HTMLElement>();

/**
* All template refs
Expand All @@ -27,6 +29,7 @@ export class TemplateWrapperComponent {

public litRender(container: HTMLElement, templateFunc: (arg: any) => TemplateResult, arg: any) {
render(templateFunc(arg), container);
this.templateRendered.next(container);
}

public addTemplate(templateFunc: TemplateFunction): TemplateRef<any> {
Expand Down
6 changes: 5 additions & 1 deletion projects/igniteui-angular-elements/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,11 @@ <h3 class="ig-typography__h6">Flat Grid (MRL column layout)</h3>
<igc-combo ${ref(focusCallback)} style="width:100%; height:100%" .data=${northwindProducts} value-key="ProductName" @igcChange=${(e) => ctx.cell.editValue = e.detail.newValue} single-select>
</igc-combo>
`;
grid1.detailTemplate = (ctx) => html`<div><span class="categoryStyle">Stock: ${ctx.implicit.InStock}</span></div>`;
grid1.detailTemplate = (ctx) => {
return html`<div>
<igc-grid auto-generate="true"></igc-grid>
</div>`;
}

grid2.querySelector('igc-column[field="ProductName"]').inlineEditorTemplate = (ctx) =>
html`
Expand Down
Loading