mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 11:17:19 +08:00
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:
@ -103,7 +103,6 @@ export class IonModal {
|
|||||||
protected el: HTMLElement;
|
protected el: HTMLElement;
|
||||||
|
|
||||||
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
|
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
|
||||||
c.detach();
|
|
||||||
this.el = r.nativeElement;
|
this.el = r.nativeElement;
|
||||||
|
|
||||||
this.el.addEventListener('willPresent', () => {
|
this.el.addEventListener('willPresent', () => {
|
||||||
|
@ -104,7 +104,6 @@ export class IonPopover {
|
|||||||
protected el: HTMLElement;
|
protected el: HTMLElement;
|
||||||
|
|
||||||
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
|
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
|
||||||
c.detach();
|
|
||||||
this.el = r.nativeElement;
|
this.el = r.nativeElement;
|
||||||
|
|
||||||
this.el.addEventListener('willPresent', () => {
|
this.el.addEventListener('willPresent', () => {
|
||||||
|
@ -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');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
18
angular/test/test-app/e2e/src/popover.spec.ts
Normal file
18
angular/test/test-app/e2e/src/popover.spec.ts
Normal 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');
|
||||||
|
});
|
||||||
|
});
|
@ -27,7 +27,9 @@ const routes: Routes = [
|
|||||||
{ path: 'inputs', component: InputsComponent },
|
{ path: 'inputs', component: InputsComponent },
|
||||||
{ path: 'form', component: FormComponent },
|
{ path: 'form', component: FormComponent },
|
||||||
{ path: 'modals', component: ModalComponent },
|
{ path: 'modals', component: ModalComponent },
|
||||||
|
{ path: 'modal-inline', loadChildren: () => import('./modal-inline').then(m => m.ModalInlineModule) },
|
||||||
{ path: 'view-child', component: ViewChildComponent },
|
{ path: 'view-child', component: ViewChildComponent },
|
||||||
|
{ path: 'popover-inline', loadChildren: () => import('./popover-inline').then(m => m.PopoverInlineModule) },
|
||||||
{ path: 'providers', component: ProvidersComponent },
|
{ path: 'providers', component: ProvidersComponent },
|
||||||
{ path: 'router-link', component: RouterLinkComponent },
|
{ path: 'router-link', component: RouterLinkComponent },
|
||||||
{ path: 'router-link-page', component: RouterLinkPageComponent },
|
{ path: 'router-link-page', component: RouterLinkPageComponent },
|
||||||
|
2
angular/test/test-app/src/app/modal-inline/index.ts
Normal file
2
angular/test/test-app/src/app/modal-inline/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './modal-inline.component';
|
||||||
|
export * from './modal-inline.module';
|
@ -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 { }
|
@ -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>
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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 { }
|
1
angular/test/test-app/src/app/popover-inline/index.ts
Normal file
1
angular/test/test-app/src/app/popover-inline/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './popover-inline.module';
|
@ -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 { }
|
@ -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>
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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 { }
|
Reference in New Issue
Block a user