Skip to content

Commit

Permalink
refactor: remove NavParams
Browse files Browse the repository at this point in the history
  • Loading branch information
liamdebeasi committed Jan 25, 2024
1 parent 1ea025d commit 745a539
Show file tree
Hide file tree
Showing 13 changed files with 60 additions and 154 deletions.
25 changes: 25 additions & 0 deletions BREAKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- [Datetime](#version-8x-datetime)
- [Nav](#version-8x-nav)
- [Picker](#version-8x-picker)
- [Angular](#version-8x-angular)

<h2 id="version-8x-browser-platform-support">Browser and Platform Support</h2>

Expand Down Expand Up @@ -143,3 +144,27 @@ This allows components to inherit the color properly when used outside of Ionic
- `ion-picker` and `ion-picker-column` have been renamed to `ion-picker-legacy` and `ion-picker-legacy-column`, respectively. This change was made to accommodate the new inline picker component while allowing developers to continue to use the legacy picker during this migration period.
- Only the component names have been changed. Usages such as `ion-picker` or `IonPicker` should be changed to `ion-picker-legacy` and `IonPickerLegacy`, respectively.
- Non-component usages such as `pickerController` or `useIonPicker` remain unchanged. The new picker displays inline with your page content and does not have equivalents for these non-component usages.

<h4 id="version-8x-angular">Angular</h4>

- NavParams has been removed in favor of using Angular's Input API. Components that accessed parameters should ensure that an input is created for each parameter:

**Old**
```js
import { NavParams } from '@ionic/angular';

console.log(this.navParams.get('myProp'));
```

**New**
```js
import { Input } from '@angular/core';

...

@Input() myProp: string;

ngOnInit() {
console.log(this.myProp)
}
```
43 changes: 0 additions & 43 deletions packages/angular/common/src/directives/navigation/nav-params.ts

This file was deleted.

5 changes: 2 additions & 3 deletions packages/angular/common/src/directives/navigation/nav.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ElementRef, Injector, EnvironmentInjector, NgZone, ChangeDetectorRef, Directive } from '@angular/core';
import { ElementRef, EnvironmentInjector, NgZone, ChangeDetectorRef, Directive } from '@angular/core';
import type { Components } from '@ionic/core';

import { AngularDelegate } from '../../providers/angular-delegate';
Expand Down Expand Up @@ -39,14 +39,13 @@ export class IonNav {
constructor(
ref: ElementRef,
environmentInjector: EnvironmentInjector,
injector: Injector,
angularDelegate: AngularDelegate,
protected z: NgZone,
c: ChangeDetectorRef
) {
c.detach();
this.el = ref.nativeElement;
ref.nativeElement.delegate = angularDelegate.create(environmentInjector, injector);
ref.nativeElement.delegate = angularDelegate.create(environmentInjector);
proxyOutputs(this, this.el, ['ionNavDidChange', 'ionNavWillChange']);
}
}
2 changes: 0 additions & 2 deletions packages/angular/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ export { bindLifecycleEvents, AngularDelegate } from './providers/angular-delega
export type { IonicWindow } from './types/interfaces';
export type { ViewWillEnter, ViewWillLeave, ViewDidEnter, ViewDidLeave } from './types/ionic-lifecycle-hooks';

export { NavParams } from './directives/navigation/nav-params';

export { IonPopover } from './overlays/popover';
export { IonModal } from './overlays/modal';

Expand Down
108 changes: 22 additions & 86 deletions packages/angular/common/src/providers/angular-delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ import {
ApplicationRef,
NgZone,
Injectable,
Injector,
EnvironmentInjector,
inject,
createComponent,
InjectionToken,
ComponentRef,
} from '@angular/core';
import {
Expand All @@ -18,27 +16,15 @@ import {
LIFECYCLE_WILL_UNLOAD,
} from '@ionic/core/components';

import { NavParams } from '../directives/navigation/nav-params';

// TODO(FW-2827): types

@Injectable()
export class AngularDelegate {
private zone = inject(NgZone);
private applicationRef = inject(ApplicationRef);

create(
environmentInjector: EnvironmentInjector,
injector: Injector,
elementReferenceKey?: string
): AngularFrameworkDelegate {
return new AngularFrameworkDelegate(
environmentInjector,
injector,
this.applicationRef,
this.zone,
elementReferenceKey
);
create(environmentInjector: EnvironmentInjector, elementReferenceKey?: string): AngularFrameworkDelegate {
return new AngularFrameworkDelegate(environmentInjector, this.applicationRef, this.zone, elementReferenceKey);
}
}

Expand All @@ -48,7 +34,6 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {

constructor(
private environmentInjector: EnvironmentInjector,
private injector: Injector,
private applicationRef: ApplicationRef,
private zone: NgZone,
private elementReferenceKey?: string
Expand Down Expand Up @@ -76,7 +61,6 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
const el = attachView(
this.zone,
this.environmentInjector,
this.injector,
this.applicationRef,
this.elRefMap,
this.elEventsMap,
Expand Down Expand Up @@ -113,7 +97,6 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
export const attachView = (
zone: NgZone,
environmentInjector: EnvironmentInjector,
injector: Injector,
applicationRef: ApplicationRef,
elRefMap: WeakMap<HTMLElement, ComponentRef<any>>,
elEventsMap: WeakMap<HTMLElement, () => void>,
Expand All @@ -123,26 +106,8 @@ export const attachView = (
cssClasses: string[] | undefined,
elementReferenceKey: string | undefined
): any => {
/**
* Wraps the injector with a custom injector that
* provides NavParams to the component.
*
* NavParams is a legacy feature from Ionic v3 that allows
* Angular developers to provide data to a component
* and access it by providing NavParams as a dependency
* in the constructor.
*
* The modern approach is to access the data directly
* from the component's class instance.
*/
const childInjector = Injector.create({
providers: getProviders(params),
parent: injector,
});

const componentRef = createComponent<any>(component, {
environmentInjector,
elementInjector: childInjector,
});

const instance = componentRef.instance;
Expand All @@ -164,37 +129,28 @@ export const attachView = (
);
}

const { modal, popover, ...otherParams } = params;
/**
* Any key/value pairs set in componentProps
* must be set as inputs on the component instance.
*/
for (const key in otherParams) {
componentRef.setInput(key, otherParams[key]);
}

/**
* Angular 14.1 added support for setInput
* so we need to fall back to Object.assign
* for Angular 14.0.
* Using setInput will cause an error when
* setting modal/popover on a component that
* does not define them as an input. For backwards
* compatibility purposes we fall back to using
* Object.assign for these properties.
*/
if (componentRef.setInput !== undefined) {
const { modal, popover, ...otherParams } = params;
/**
* Any key/value pairs set in componentProps
* must be set as inputs on the component instance.
*/
for (const key in otherParams) {
componentRef.setInput(key, otherParams[key]);
}

/**
* Using setInput will cause an error when
* setting modal/popover on a component that
* does not define them as an input. For backwards
* compatibility purposes we fall back to using
* Object.assign for these properties.
*/
if (modal !== undefined) {
Object.assign(instance, { modal });
}

if (popover !== undefined) {
Object.assign(instance, { popover });
}
} else {
Object.assign(instance, params);
if (modal !== undefined) {
Object.assign(instance, { modal });
}

if (popover !== undefined) {
Object.assign(instance, { popover });
}
}
if (cssClasses) {
Expand Down Expand Up @@ -230,23 +186,3 @@ export const bindLifecycleEvents = (zone: NgZone, instance: any, element: HTMLEl
return () => unregisters.forEach((fn) => fn());
});
};

const NavParamsToken = new InjectionToken<any>('NavParamsToken');

const getProviders = (params: { [key: string]: any }) => {
return [
{
provide: NavParamsToken,
useValue: params,
},
{
provide: NavParams,
useFactory: provideNavParamsInjectable,
deps: [NavParamsToken],
},
];
};

const provideNavParamsInjectable = (params: { [key: string]: any }) => {
return new NavParams(params);
};
4 changes: 1 addition & 3 deletions packages/angular/src/directives/navigation/ion-nav.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
ElementRef,
Injector,
EnvironmentInjector,
NgZone,
ChangeDetectorRef,
Expand All @@ -19,11 +18,10 @@ export class IonNav extends IonNavBase {
constructor(
ref: ElementRef,
environmentInjector: EnvironmentInjector,
injector: Injector,
angularDelegate: AngularDelegate,
z: NgZone,
c: ChangeDetectorRef
) {
super(ref, environmentInjector, injector, angularDelegate, z, c);
super(ref, environmentInjector, angularDelegate, z, c);
}
}
1 change: 0 additions & 1 deletion packages/angular/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export {
Config,
Platform,
AngularDelegate,
NavParams,
IonicRouteStrategy,
ViewWillEnter,
ViewWillLeave,
Expand Down
5 changes: 2 additions & 3 deletions packages/angular/src/providers/modal-controller.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Injector, Injectable, EnvironmentInjector, inject } from '@angular/core';
import { Injectable, EnvironmentInjector, inject } from '@angular/core';
import { AngularDelegate, OverlayBaseController } from '@ionic/angular/common';
import type { ModalOptions } from '@ionic/core';
import { modalController } from '@ionic/core';

@Injectable()
export class ModalController extends OverlayBaseController<ModalOptions, HTMLIonModalElement> {
private angularDelegate = inject(AngularDelegate);
private injector = inject(Injector);
private environmentInjector = inject(EnvironmentInjector);

constructor() {
Expand All @@ -16,7 +15,7 @@ export class ModalController extends OverlayBaseController<ModalOptions, HTMLIon
create(opts: ModalOptions): Promise<HTMLIonModalElement> {
return super.create({
...opts,
delegate: this.angularDelegate.create(this.environmentInjector, this.injector, 'modal'),
delegate: this.angularDelegate.create(this.environmentInjector, 'modal'),
});
}
}
5 changes: 2 additions & 3 deletions packages/angular/src/providers/popover-controller.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Injector, inject, EnvironmentInjector } from '@angular/core';
import { inject, EnvironmentInjector } from '@angular/core';
import { AngularDelegate, OverlayBaseController } from '@ionic/angular/common';
import type { PopoverOptions } from '@ionic/core';
import { popoverController } from '@ionic/core';

export class PopoverController extends OverlayBaseController<PopoverOptions, HTMLIonPopoverElement> {
private angularDelegate = inject(AngularDelegate);
private injector = inject(Injector);
private environmentInjector = inject(EnvironmentInjector);

constructor() {
Expand All @@ -15,7 +14,7 @@ export class PopoverController extends OverlayBaseController<PopoverOptions, HTM
create(opts: PopoverOptions): Promise<HTMLIonPopoverElement> {
return super.create({
...opts,
delegate: this.angularDelegate.create(this.environmentInjector, this.injector, 'popover'),
delegate: this.angularDelegate.create(this.environmentInjector, 'popover'),
});
}
}
1 change: 0 additions & 1 deletion packages/angular/standalone/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export {
NavController,
Config,
Platform,
NavParams,
IonicRouteStrategy,
ViewWillEnter,
ViewDidEnter,
Expand Down
5 changes: 2 additions & 3 deletions packages/angular/standalone/src/navigation/nav.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, ElementRef, Injector, EnvironmentInjector, NgZone, ChangeDetectorRef } from '@angular/core';
import { Component, ElementRef, EnvironmentInjector, NgZone, ChangeDetectorRef } from '@angular/core';
import { IonNav as IonNavBase, ProxyCmp, AngularDelegate } from '@ionic/angular/common';
import { defineCustomElement } from '@ionic/core/components/ion-nav.js';

Expand All @@ -14,11 +14,10 @@ export class IonNav extends IonNavBase {
constructor(
ref: ElementRef,
environmentInjector: EnvironmentInjector,
injector: Injector,
angularDelegate: AngularDelegate,
z: NgZone,
c: ChangeDetectorRef
) {
super(ref, environmentInjector, injector, angularDelegate, z, c);
super(ref, environmentInjector, angularDelegate, z, c);
}
}
Loading

0 comments on commit 745a539

Please sign in to comment.