Skip to content
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions cypress/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"extends": "../tsconfig.json",
"include": ["**/*.ts"],
"compilerOptions": {
/* TODO: interim override — remove once cypress specs are migrated to strict */
"strict": false,
"noImplicitOverride": true,
"sourceMap": false,
"types": ["cypress"]
}
Expand Down
18 changes: 18 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
"@types/express": "^5.0.0",
"@types/jasmine": "^5.1.7",
"@types/jasminewd2": "^2.0.10",
"@types/lodash-es": "^4.17.12",
"@types/node": "^20.17.6",
"@types/sass-true": "^6.0.2",
"@types/webpack-env": "^1.18.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function createIgxCustomElement<T>(component: Type<T>, config: IgxNgEleme

const componentConfig = config.registerConfig?.find(x => x.component === component);

for (const method of componentConfig?.methods) {
for (const method of componentConfig?.methods!) {
elementCtor.prototype[method] = function() {
const instance = this.ngElementStrategy.componentRef.instance;
return this.ngElementStrategy.runInZone(() => instance[method].apply(instance, arguments));
Expand All @@ -29,7 +29,7 @@ export function createIgxCustomElement<T>(component: Type<T>, config: IgxNgEleme

// Reuse `createCustomElement`'s approach for Inputs, should work for any prop too:
componentConfig?.additionalProperties.forEach((p) => {
let set: (v: any) => void | undefined;
let set!: (v: any) => void | undefined;


if (p.name in elementCtor.prototype) {
Expand All @@ -38,7 +38,7 @@ export function createIgxCustomElement<T>(component: Type<T>, config: IgxNgEleme
}

if (p.writable) {
set = function (newValue) {
set = function (this: any, newValue: any) {
this.ngElementStrategy.setInputValue(p.name, newValue);
}
}
Expand Down Expand Up @@ -111,7 +111,7 @@ function guardAttributeNames<T>(strategyFactory: IgxCustomNgElementStrategyFacto

// getComponentDef not public, also technically readonly map
// the key is the non-minified (template) name
const inputs = reflectComponentType((strategyFactory as any).component).inputs;
const inputs = reflectComponentType((strategyFactory as any).component)!.inputs;

inputs.forEach((input) => {
const key = input.templateName;
Expand All @@ -123,7 +123,7 @@ function guardAttributeNames<T>(strategyFactory: IgxCustomNgElementStrategyFacto

// const newKey = key.replace(/(?<=[A-Z])[A-Z]+(?![a-z])/g, char => char.toLowerCase()); // no Lookbehind assertion in Safari yet
const newKey = key.replace(/([A-Z])([A-Z]+)(?![a-z])/g, (match, p1, p2) => p1 + p2.toLowerCase());
inputs[newKey] = input;
(inputs as any)[newKey] = input;
// TODO: consider deleting the original key
}
});
Expand Down
64 changes: 32 additions & 32 deletions projects/igniteui-angular-elements/src/app/custom-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const SCHEDULE_DELAY = 10;

/** @hidden @internal */
export abstract class IgcNgElement extends NgElement {
public override readonly ngElementStrategy: IgxCustomNgElementStrategy;
public override readonly ngElementStrategy!: IgxCustomNgElementStrategy;
}

/**
Expand All @@ -23,14 +23,14 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {

// public override componentRef: ComponentRef<any>|null = null;

protected element: IgcNgElement;
protected element!: IgcNgElement;
/** The parent _component_'s element (a.k.a the semantic parent, rather than the DOM one after projection) */
protected parentElement?: WeakRef<IgcNgElement>;
/** Native Angular parent (if any) the Element is created under, usually as template of dynamic component (e.g. HGrid row island paginator) */
protected angularParent: ComponentRef<any>;
protected angularParent!: ComponentRef<any>;
/** Cached child instances per query prop. Used for dynamic components's child templates that normally persist in Angular runtime */
protected cachedChildComponents: Map<string, ComponentRef<any>[]> = new Map();
private setComponentRef: (value: ComponentRef<any>) => void;
private setComponentRef!: (value: ComponentRef<any>) => void;
/** The maximum depth at which event arguments are processed and angular components wrapped with Proxies, that handle template set */
private maxEventProxyDepth = 3;

Expand All @@ -43,7 +43,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
*/
public [ComponentRefKey] = new Promise<ComponentRef<any>>((resolve, _) => this.setComponentRef = resolve);

private _templateWrapperRef: ComponentRef<TemplateWrapperComponent>;
private _templateWrapperRef!: ComponentRef<TemplateWrapperComponent>;
protected get templateWrapper(): TemplateWrapperComponent {
if (!this._templateWrapperRef) {
const componentRef = (this as any).componentRef as ComponentRef<any>;
Expand All @@ -53,7 +53,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
return this._templateWrapperRef.instance;
}

private _configSelectors: string;
private _configSelectors!: string;
public get configSelectors(): string {
if (!this._configSelectors) {
this._configSelectors = this.config.map(x => x.selector).join(',');
Expand Down Expand Up @@ -82,7 +82,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
// set componentRef to non-null to prevent DOM moves from re-initializing
// TODO: Fail handling or cancellation needed?
(this as any).componentRef = {};
const ngContentSelectors = [...reflectComponentType(this._component).ngContentSelectors];
const ngContentSelectors = [...reflectComponentType(this._component)!.ngContentSelectors];
const contentChildrenTags = Array.from(element.children)
.filter(x => ngContentSelectors.some(sel => x.matches(sel)))
.map(x => x.tagName.toLocaleLowerCase());
Expand All @@ -91,22 +91,22 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
// for (const iterator of toBeOrphanedChildren) {
// // TODO: special registration OR config for custom
// }
let parentInjector: Injector;
let parentAnchor: ViewContainerRef;
let parentInjector!: Injector;
let parentAnchor!: ViewContainerRef;
const parents: WeakRef<IgcNgElement>[] = [];
const componentConfig = this.config?.find(x => x.component === this._component);

const configParents = componentConfig?.parents
.map(parentType => this.config.find(x => x.component === parentType))
.filter(x => x.selector);
.filter(x => x!.selector);

if (configParents?.length) {
let node = element as IgcNgElement;
while (node?.parentElement) {
node = node.parentElement.closest<IgcNgElement>(configParents.flatMap(x => [
x.selector,
reflectComponentType(x.component).selector
]).join(','));
x!.selector,
reflectComponentType(x!.component)!.selector
]).join(','))!;
if (node) {
parents.push(new WeakRef(node));
}
Expand All @@ -115,7 +115,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
let parent = parents[0]?.deref();

// Collected parents may include direct Angular HGrids, so only wait for configured parent elements:
const configParent = configParents.find(x => x.selector === parent?.tagName.toLocaleLowerCase());
const configParent = configParents.find(x => x!.selector === parent?.tagName.toLocaleLowerCase());
if (configParent && !customElements.get(configParent.selector)) {
await customElements.whenDefined(configParent.selector);
}
Expand Down Expand Up @@ -178,21 +178,21 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
// check if there are any content children associated with a content query collection.
// if no, then just emit the event, otherwise we wait for the collection to be updated in updateQuery.
const contentChildrenTypes = this.config.filter(x => contentChildrenTags.indexOf(x.selector) !== -1).map(x => x.provideAs ?? x.component);
const contentQueryChildrenCollection = componentConfig.contentQueries.filter(x => contentChildrenTypes.includes(x.childType));
const contentQueryChildrenCollection = componentConfig!.contentQueries.filter(x => contentChildrenTypes.includes(x.childType));
if (contentQueryChildrenCollection.length === 0) {
// no content children, emit event immediately, since there's nothing to be attached.
(this as any).componentRef?.instance?.childrenResolved?.emit();
}

if (parentAnchor && parentInjector) {
// attempt to attach the newly created ViewRef to the parents's instead of the App global
const parentViewRef = parentInjector.get<ViewContainerRef>(ViewContainerRef);
// const parentViewRef = parentInjector.get<ViewContainerRef>(ViewContainerRef);
// preserve original position in DOM (in case of projection, e.g. grid pager):
const domParent = element.parentElement;
const nextSibling = element.nextSibling;
parentAnchor.insert((this as any).componentRef.hostView); //bad, moves in DOM, AND need to be in inner anchor :S
//restore original DOM position
domParent.insertBefore(element, nextSibling);
domParent!.insertBefore(element, nextSibling);
(this as any).componentRef.hostView.detectChanges();
} else if (!parentAnchor) {
(this as any).appRef.attachView((this as any).componentRef.hostView);
Expand All @@ -205,7 +205,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
// componentRef should also likely be protected:
const componentRef = (this as any).componentRef as ComponentRef<any>;

const parentQueries = this.getParentContentQueries(componentConfig, parents, configParents);
const parentQueries = this.getParentContentQueries(componentConfig!, parents as any, configParents as any);

for (const { parent, query } of parentQueries) {
if (query.isQueryList) {
Expand All @@ -230,11 +230,11 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
componentRef.onDestroy(() => {
if (this._templateWrapperRef) {
this._templateWrapperRef.destroy();
this._templateWrapperRef = null;
this._templateWrapperRef = null!;
}

// also schedule query updates on all parents:
this.getParentContentQueries(componentConfig, parents, configParents)
this.getParentContentQueries(componentConfig!, parents as any, configParents as any)
.filter(x => x.parent?.isConnected && x.query.isQueryList)
.forEach(({ parent, query }) => {
parent.ngElementStrategy.scheduleQueryUpdate(query.property);
Expand Down Expand Up @@ -289,7 +289,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
}

// TODO(D.P.): Check API use and expose needed props to avoid unwrap OR handle component ref props w/ config
if (componentConfig.selector === 'igc-pivot-data-selector' && property === 'grid' && value) {
if (componentConfig!.selector === 'igc-pivot-data-selector' && property === 'grid' && value) {
value = value.ngElementStrategy?.componentRef?.instance || value;
}
super.setInputValue(property, value);
Expand All @@ -316,7 +316,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
*/
public scheduleQueryUpdate(queryName: string) {
if (this.schedule.has(queryName)) {
this.schedule.get(queryName)();
this.schedule.get(queryName)!();
}

const id = setTimeout(() => this.updateQuery(queryName), SCHEDULE_DELAY);
Expand All @@ -328,8 +328,8 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
const componentRef = (this as any).componentRef as ComponentRef<any>;
if (componentRef) {
const componentConfig = this.config?.find(x => x.component === this._component);
const query = componentConfig.contentQueries.find(x => x.property === queryName);
const children = this.runQueryInDOM(this.element, query);
const query = componentConfig!.contentQueries.find(x => x.property === queryName);
const children = this.runQueryInDOM(this.element, query!);
let childRefs = [];
for (const child of children) {
// D.P. Use sync componentRef to avoid having this being stuck waiting while another update is queued
Expand All @@ -342,10 +342,10 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
childRefs.push(childRef.instance);
}
}
if (query.descendants && this.cachedChildComponents.has(queryName)) {
childRefs = [...this.cachedChildComponents.get(queryName), ...childRefs];
if (query!.descendants && this.cachedChildComponents.has(queryName)) {
childRefs = [...this.cachedChildComponents.get(queryName)!, ...childRefs];
}
const list = (this as any).componentRef.instance[query.property] as QueryList<any>;
const list = (this as any).componentRef.instance[query!.property] as QueryList<any>;
list.reset(childRefs);
list.notifyOnChanges();
}
Expand All @@ -369,7 +369,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
const parents = new Set(childConfigs.map(x => x.parents).flat());
const parentSelectors = this.config.filter(x => parents.has(x.component)).map(x => x.selector).filter(x => x).join(',');

children = children.filter(x => x.parentElement.closest(parentSelectors) === element);
children = children.filter(x => x.parentElement!.closest(parentSelectors) === element);
}
return children;
}
Expand Down Expand Up @@ -408,7 +408,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
if (i > 0 && !query.descendants) {
continue;
}
queries.push({ parent, query });
queries.push({ parent: parent!, query });
}
}

Expand Down Expand Up @@ -441,7 +441,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
}
});

fromEvent(this.element, 'igcOpened').pipe(takeUntil(componentRef.instance.destroy$)).subscribe((e: CustomEvent) => {
fromEvent<CustomEvent>(this.element, 'igcOpened').pipe(takeUntil(componentRef.instance.destroy$)).subscribe(e => {
if (!Object.keys(e.detail).length) {
// toggle directive-based components emit void details
// TODO: need better flag
Expand All @@ -462,7 +462,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
//#region Handle event args that return reference to components, since they return angular ref and not custom elements.
/** Sets up listeners for the component's outputs so that the events stream emits the events. */
protected override initializeOutputs(componentRef: ComponentRef<any>): void {
const eventEmitters: Observable<NgElementStrategyEvent>[] = reflectComponentType(this._component).outputs.map(
const eventEmitters: Observable<NgElementStrategyEvent>[] = reflectComponentType(this._component)!.outputs.map(
({ propName, templateName }) => {
const emitter: EventEmitter<any> = componentRef.instance[propName];
return emitter.pipe(map((value: any) => ({ name: templateName, value: this.patchOutputComponents(propName, value) })));
Expand Down Expand Up @@ -530,7 +530,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
return new Proxy(component, {
set(target: any, prop: string, newValue: any) {
// For now handle only template props
if (config.templateProps.includes(prop)) {
if (config.templateProps!.includes(prop)) {
const oldRef = target[prop];
const oldValue = oldRef && parentThis.templateWrapper.getTemplateFunction(oldRef);
if (oldValue === newValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export class TemplateRefWrapper<C extends object> extends TemplateRef<C> {

/** @internal */
class TemplateRefWrapperContentContext {
public _id: string;
public _id!: string;
public root: any;
public templateFunction: any;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class TemplateWrapperComponent {
* (internally creates one like the old `<ng-template ngFor` would). TODO(D.P.): filter it out?
*/
@ViewChildren(TemplateRef)
public templateRefs: QueryList<TemplateRef<any>>;
public templateRefs!: QueryList<TemplateRef<any>>;

protected litRender(container: HTMLElement, templateFunc: (arg: any) => TemplateResult, arg: any) {
const part = render(templateFunc(arg), container);
Expand Down Expand Up @@ -68,7 +68,7 @@ export class TemplateWrapperComponent {
*/
protected embeddedViewDestroyCallback = (container: HTMLElement) => {
if (container && this.childParts.has(container)) {
this.childParts.get(container).setConnected(false);
this.childParts.get(container)!.setConnected(false);
this.childParts.delete(container);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export class IgxGridComponent extends IgxGrid {
/* blazorCollectionItemName: ActionStrip */
/* ngQueryListName: actionStripComponents */
@ContentChildren(IgxActionStripToken)
protected override actionStripComponents: QueryList<IgxActionStripToken>;
protected override actionStripComponents!: QueryList<IgxActionStripToken>;

protected override autogenerateColumns() {
super.autogenerateColumns();
Expand Down
Loading
Loading