fix(angular): attach change detector ref for inline overlays (#24521)

Allow template bindings to update with inline overlays.

Resolves #24502
This commit is contained in:
Sean Perkins
2022-01-06 15:43:51 -05:00
committed by GitHub
parent bd82b5dc1d
commit 5c54593dde
15 changed files with 161 additions and 2 deletions

View File

@ -103,7 +103,6 @@ export class IonModal {
protected el: HTMLElement;
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
c.detach();
this.el = r.nativeElement;
this.el.addEventListener('willPresent', () => {

View File

@ -104,7 +104,6 @@ export class IonPopover {
protected el: HTMLElement;
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
c.detach();
this.el = r.nativeElement;
this.el.addEventListener('willPresent', () => {

View File

@ -41,3 +41,23 @@ describe('Modals', () => {
});
});
describe('Modals: Inline', () => {
beforeEach(() => {
cy.visit('/modal-inline');
});
it('should initially have no items', () => {
cy.get('ion-list ion-item').should('not.exist');
});
it('should have items after 1500ms', () => {
cy.wait(1500);
cy.get('ion-list ion-item:nth-child(1)').should('have.text', 'A');
cy.get('ion-list ion-item:nth-child(2)').should('have.text', 'B');
cy.get('ion-list ion-item:nth-child(3)').should('have.text', 'C');
cy.get('ion-list ion-item:nth-child(4)').should('have.text', 'D');
});
});

View File

@ -0,0 +1,18 @@
describe('Popovers: Inline', () => {
beforeEach(() => {
cy.visit('/popover-inline');
});
it('should initially have no items', () => {
cy.get('ion-list ion-item').should('not.exist');
});
it('should have items after 1500ms', () => {
cy.wait(1500);
cy.get('ion-list ion-item:nth-child(1)').should('have.text', 'A');
cy.get('ion-list ion-item:nth-child(2)').should('have.text', 'B');
cy.get('ion-list ion-item:nth-child(3)').should('have.text', 'C');
cy.get('ion-list ion-item:nth-child(4)').should('have.text', 'D');
});
});

View File

@ -27,7 +27,9 @@ const routes: Routes = [
{ path: 'inputs', component: InputsComponent },
{ path: 'form', component: FormComponent },
{ path: 'modals', component: ModalComponent },
{ path: 'modal-inline', loadChildren: () => import('./modal-inline').then(m => m.ModalInlineModule) },
{ path: 'view-child', component: ViewChildComponent },
{ path: 'popover-inline', loadChildren: () => import('./popover-inline').then(m => m.PopoverInlineModule) },
{ path: 'providers', component: ProvidersComponent },
{ path: 'router-link', component: RouterLinkComponent },
{ path: 'router-link-page', component: RouterLinkPageComponent },

View File

@ -0,0 +1,2 @@
export * from './modal-inline.component';
export * from './modal-inline.module';

View File

@ -0,0 +1,16 @@
import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { ModalInlineComponent } from ".";
@NgModule({
imports: [
RouterModule.forChild([
{
path: '',
component: ModalInlineComponent
}
])
],
exports: [RouterModule]
})
export class ModalInlineRoutingModule { }

View File

@ -0,0 +1,11 @@
<ion-modal [isOpen]="true" [breakpoints]="[0.1, 0.5, 1]" [initialBreakpoint]="0.5">
<ng-template>
<ion-content>
<ion-list>
<ion-item *ngFor="let item of items">
<ion-label>{{ item }}</ion-label>
</ion-item>
</ion-list>
</ion-content>
</ng-template>
</ion-modal>

View File

@ -0,0 +1,21 @@
import { AfterViewInit, Component } from "@angular/core";
/**
* Validates that inline modals will correctly display
* dynamic contents that are updated after the modal is
* display.
*/
@Component({
selector: 'app-modal-inline',
templateUrl: 'modal-inline.component.html'
})
export class ModalInlineComponent implements AfterViewInit {
items: string[] = [];
ngAfterViewInit(): void {
setTimeout(() => {
this.items = ['A', 'B', 'C', 'D'];
}, 1000);
}
}

View File

@ -0,0 +1,12 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { IonicModule } from "@ionic/angular";
import { ModalInlineRoutingModule } from "./modal-inline-routing.module";
import { ModalInlineComponent } from "./modal-inline.component";
@NgModule({
imports: [CommonModule, IonicModule, ModalInlineRoutingModule],
declarations: [ModalInlineComponent],
exports: [ModalInlineComponent]
})
export class ModalInlineModule { }

View File

@ -0,0 +1 @@
export * from './popover-inline.module';

View File

@ -0,0 +1,14 @@
import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { PopoverInlineComponent } from "./popover-inline.component";
@NgModule({
imports: [RouterModule.forChild([
{
path: '',
component: PopoverInlineComponent
}
])],
exports: [RouterModule]
})
export class PopoverInlineRoutingModule { }

View File

@ -0,0 +1,11 @@
<ion-popover [isOpen]="true">
<ng-template>
<ion-content>
<ion-list>
<ion-item *ngFor="let item of items">
<ion-label>{{ item }}</ion-label>
</ion-item>
</ion-list>
</ion-content>
</ng-template>
</ion-popover>

View File

@ -0,0 +1,22 @@
import { AfterViewInit, Component } from "@angular/core";
/**
* Validates that inline popovers will correctly display
* dynamic contents that are updated after the modal is
* display.
*/
@Component({
selector: 'app-popover-inline',
templateUrl: 'popover-inline.component.html'
})
export class PopoverInlineComponent implements AfterViewInit {
items: string[] = [];
ngAfterViewInit(): void {
setTimeout(() => {
this.items = ['A', 'B', 'C', 'D'];
}, 1000);
}
}

View File

@ -0,0 +1,11 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { IonicModule } from "@ionic/angular";
import { PopoverInlineRoutingModule } from "./popover-inline-routing.module";
import { PopoverInlineComponent } from "./popover-inline.component";
@NgModule({
imports: [CommonModule, IonicModule, PopoverInlineRoutingModule],
declarations: [PopoverInlineComponent],
})
export class PopoverInlineModule { }