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
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ export class NavDelegate {
ref: ElementRef,
environmentInjector: EnvironmentInjector,
injector: Injector,
// TODO FW-4766: Remove AngularDelegate
angularDelegate: AngularDelegate,
protected z: NgZone
) {
Expand Down
1 change: 0 additions & 1 deletion packages/angular/src/directives/navigation/nav-delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export class NavDelegate extends NavDelegateBase {
ref: ElementRef,
environmentInjector: EnvironmentInjector,
injector: Injector,
// TODO FW-4766: Remove AngularDelegate
angularDelegate: AngularDelegate,
z: NgZone
) {
Expand Down
2 changes: 1 addition & 1 deletion packages/angular/standalone/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export { IonPopover } from './overlays/popover';
export { IonRouterOutlet } from './navigation/router-outlet';
export { IonRouterLink, IonRouterLinkWithHref } from './navigation/router-link-delegate';
export { IonNav } from './navigation/nav-delegate';

export { provideIonicAngular } from './providers/ionic-angular';
export {
ActionSheetController,
AlertController,
Expand Down
1 change: 0 additions & 1 deletion packages/angular/standalone/src/navigation/nav-delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export class IonNav extends NavDelegateBase {
ref: ElementRef,
environmentInjector: EnvironmentInjector,
injector: Injector,
// TODO FW-4766: Remove AngularDelegate
angularDelegate: AngularDelegate,
z: NgZone
) {
Expand Down
51 changes: 51 additions & 0 deletions packages/angular/standalone/src/providers/ionic-angular.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { DOCUMENT } from '@angular/common';
import { APP_INITIALIZER } from '@angular/core';
import type { Provider } from '@angular/core';
import {
AngularDelegate,
ConfigToken,
ModalController,
PopoverController,
provideComponentInputBinding,
} from '@ionic/angular/common';
import { initialize } from '@ionic/core/components';
import type { IonicConfig } from '@ionic/core/components';

export const provideIonicAngular = (config?: IonicConfig): Provider[] => {
/**
* TODO FW-4967
* Use makeEnvironmentProviders once Angular 14 support is dropped.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried copy and pasting the implementation of makeEnvironmentProviders. This worked on ng15+ but broke on ng14. I'm not aware of a way to do feature detection here, so I opted to go without it for now.

* This prevents provideIonicAngular from being accidentally referenced in an @Component.
*/
return [
{
provide: ConfigToken,
useValue: config,
},
{
provide: APP_INITIALIZER,
useFactory: initializeIonicAngular,
multi: true,
deps: [ConfigToken, DOCUMENT],
},
provideComponentInputBinding(),
AngularDelegate,
ModalController,
PopoverController,
];
};

const initializeIonicAngular = (config: IonicConfig, doc: Document) => {
return () => {
/**
* By default Ionic Framework hides elements that
* are not hydrated, but in the CE build there is no
* hydration.
* TODO FW-2797: Remove when all integrations have been
* migrated to CE build.
*/
doc.documentElement.classList.add('ion-ce');

initialize(config);
};
};
23 changes: 23 additions & 0 deletions packages/angular/test/apps/ng14/src/main-standalone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { importProvidersFrom } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { provideIonicAngular, IonicRouteStrategy } from '@ionic/angular/standalone';

import { AppComponentStandalone } from './app/app-standalone.component';
import { AppRoutingModule } from './app/app-routing.module';

import { routes } from './app/app.routes';

export const bootstrapStandalone = () => {
bootstrapApplication(AppComponentStandalone, {
providers: [
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
/**
* provideRouter is not available in Angular 14, so
* we fallback to using AppRoutingModule
*/
importProvidersFrom(AppRoutingModule),
provideIonicAngular({ keyboardHeight: 12345 })
],
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
describe('Overlay Controllers', () => {
beforeEach(() => {
cy.visit('/standalone/overlay-controllers');
})

it('should present a modal', () => {
cy.get('button#open-modal').click();

cy.get('ion-modal app-dialog-content').should('be.visible');
});

it('should present a popover', () => {
cy.get('button#open-popover').click();

cy.get('ion-popover app-dialog-content').should('be.visible');
});
})
11 changes: 11 additions & 0 deletions packages/angular/test/base/e2e/src/standalone/providers.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
describe('Providers', () => {
beforeEach(() => {
cy.visit('/standalone/providers');
})

it('provideIonicAngular should initialize Ionic and set config correctly', () => {
cy.ionPageVisible('app-providers');

cy.get('#keyboard-height').should('have.text', '12345');
});
})
11 changes: 11 additions & 0 deletions packages/angular/test/base/src/app/app-standalone.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Component } from '@angular/core';
import { RouterModule } from '@angular/router';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
standalone: true,
imports: [RouterModule]
})
export class AppComponentStandalone {
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
import { Component } from '@angular/core';
import { RouterModule } from '@angular/router';
import { IonRouterOutlet } from '@ionic/angular/standalone';
/**
* This temporary code initialized Ionic and ensures components are visible.
* TODO FW-4766 Can be removed when ticket is implemented
*/
import { initialize } from '@ionic/core/components';
initialize();

document.querySelector('html')!.classList.add('ion-ce')


@Component({
selector: 'app-root-standalone',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const routes: Routes = [
{ path: 'back-button', loadComponent: () => import('../back-button/back-button.component').then(m => m.BackButtonComponent) },
{ path: 'router-link', loadComponent: () => import('../router-link/router-link.component').then(m => m.RouterLinkComponent) },
{ path: 'nav', loadComponent: () => import('../nav/nav.component').then(m => m.NavComponent) },
{ path: 'providers', loadComponent: () => import('../providers/providers.component').then(m => m.ProvidersComponent) },
{ path: 'overlay-controllers', loadComponent: () => import('../overlay-controllers/overlay-controllers.component').then(m => m.OverlayControllersComponent) },
]
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import { PageOneComponent } from './page-one.component';
selector: 'app-nav',
templateUrl: './nav.component.html',
standalone: true,
imports: [IonNav],
// TODO FW-4766: Remove AngularDelegate from providers
providers: [AngularDelegate]
imports: [IonNav]
})
export class NavComponent {
component = PageOneComponent;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div>
<button id="open-modal" (click)="openModal()">Open Modal</button>
<button id="open-popover" (click)="openPopover($event)">Open Popover</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Component } from '@angular/core';
import { ModalController, PopoverController } from '@ionic/angular/standalone';

@Component({
selector: 'app-overlay-controllers',
templateUrl: './overlay-controllers.component.html',
standalone: true,
})
export class OverlayControllersComponent {
constructor(private modalCtrl: ModalController, private popoverCtrl: PopoverController) {}

async openModal() {
const modal = await this.modalCtrl.create({
component: DialogComponent
});

await modal.present();
}

async openPopover(ev: MouseEvent) {
const popover = await this.popoverCtrl.create({
component: DialogComponent,
event: ev
});

await popover.present();
}
}

@Component({
selector: 'app-dialog-content',
template: '<div class="ion-padding">Dialog Content</div>',
standalone: true,
})
class DialogComponent {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<ul>
<li>Keyboard Height: <span id="keyboard-height">{{ keyboardHeight }}</span></li>
</ul>

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Component } from '@angular/core';
import { Config } from '@ionic/angular/standalone';

@Component({
selector: 'app-providers',
templateUrl: './providers.component.html',
standalone: true,
})
export class ProvidersComponent {
keyboardHeight?: number;

constructor(private config: Config) {
this.keyboardHeight = config.get('keyboardHeight');
}
}
17 changes: 17 additions & 0 deletions packages/angular/test/base/src/main-standalone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { RouteReuseStrategy, provideRouter } from '@angular/router';
import { provideIonicAngular, IonicRouteStrategy } from '@ionic/angular/standalone';

import { AppComponentStandalone } from './app/app-standalone.component';

import { routes } from './app/app.routes';

export const bootstrapStandalone = () => {
bootstrapApplication(AppComponentStandalone, {
providers: [
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
provideRouter(routes),
provideIonicAngular({ keyboardHeight: 12345 })
],
});
}
22 changes: 17 additions & 5 deletions packages/angular/test/base/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,20 @@ if (environment.production) {
enableProdMode();
}

document.addEventListener('DOMContentLoaded', () => {
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
});
const isLazy = window.location.href.includes('lazy');

if (isLazy) {
document.addEventListener('DOMContentLoaded', () => {
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
});
} else {
/**
* Importing standalone and lazy modules in the same
* file creates side effects where manually generated components
* such as ion-modal do not get bootstrapped correctly. Using
* a dynamic import avoids this.
*/
import('./main-standalone').then((module) => { module.bootstrapStandalone() });
}