Skip to content

Commit 6b33ee5

Browse files
authored
Merge pull request #571 from NativeScript/hdeshev/modal-changedetection
fix(dialogs): Trigger change detection on dialog close.
2 parents fcc08b4 + 94a38d0 commit 6b33ee5

File tree

2 files changed

+106
-101
lines changed

2 files changed

+106
-101
lines changed

nativescript-angular/common/detached-loader.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ export class DetachedLoader { // tslint:disable-line:component-class-suffix
4141
return Promise.resolve(componentRef);
4242
}
4343

44+
public detectChanges() {
45+
this.changeDetector.markForCheck();
46+
}
47+
4448
// TODO: change this API -- async promises not needed here anymore.
4549
public loadComponent(componentType: Type<any>): Promise<ComponentRef<any>> {
4650
log("DetachedLoader.loadComponent");
Lines changed: 102 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,102 @@
1-
import {
2-
ReflectiveInjector, ComponentFactoryResolver, ViewContainerRef,
3-
Type, Injectable, ComponentRef, Directive
4-
} from "@angular/core";
5-
import { Page } from "ui/page";
6-
import { View } from "ui/core/view";
7-
import { DetachedLoader } from "../common/detached-loader";
8-
import { PageFactory, PAGE_FACTORY } from "../platform-providers";
9-
10-
export interface ModalDialogOptions {
11-
context?: any;
12-
fullscreen?: boolean;
13-
viewContainerRef?: ViewContainerRef;
14-
}
15-
16-
export class ModalDialogParams {
17-
constructor(
18-
public context: any = {},
19-
public closeCallback: (...args) => any) {
20-
}
21-
}
22-
23-
@Injectable()
24-
export class ModalDialogService {
25-
public showModal(type: Type<any>, options: ModalDialogOptions): Promise<any> {
26-
if (!options.viewContainerRef) {
27-
throw new Error(
28-
"No viewContainerRef: Make sure you pass viewContainerRef in ModalDialogOptions.");
29-
}
30-
31-
const viewContainerRef = options.viewContainerRef;
32-
const parentPage: Page = viewContainerRef.injector.get(Page);
33-
const resolver: ComponentFactoryResolver = viewContainerRef.injector.get(
34-
ComponentFactoryResolver);
35-
const pageFactory: PageFactory = viewContainerRef.injector.get(PAGE_FACTORY);
36-
37-
return new Promise((resolve) => {
38-
setTimeout(() => ModalDialogService.showDialog(
39-
type,
40-
options,
41-
resolve,
42-
viewContainerRef,
43-
resolver,
44-
parentPage,
45-
pageFactory
46-
), 10);
47-
});
48-
}
49-
50-
private static showDialog(
51-
type: Type<any>,
52-
options: ModalDialogOptions,
53-
doneCallback,
54-
containerRef: ViewContainerRef,
55-
resolver: ComponentFactoryResolver,
56-
parentPage: Page,
57-
pageFactory: PageFactory): void {
58-
59-
const page = pageFactory({ isModal: true, componentType: type });
60-
61-
let detachedLoaderRef: ComponentRef<DetachedLoader>;
62-
const closeCallback = (...args) => {
63-
doneCallback.apply(undefined, args);
64-
page.closeModal();
65-
detachedLoaderRef.destroy();
66-
};
67-
68-
const modalParams = new ModalDialogParams(options.context, closeCallback);
69-
70-
const providers = ReflectiveInjector.resolve([
71-
{ provide: Page, useValue: page },
72-
{ provide: ModalDialogParams, useValue: modalParams },
73-
]);
74-
75-
const childInjector = ReflectiveInjector.fromResolvedProviders(
76-
providers, containerRef.parentInjector);
77-
const detachedFactory = resolver.resolveComponentFactory(DetachedLoader);
78-
detachedLoaderRef = containerRef.createComponent(detachedFactory, -1, childInjector, null);
79-
detachedLoaderRef.instance.loadComponent(type).then((compRef) => {
80-
const componentView = <View>compRef.location.nativeElement;
81-
82-
if (componentView.parent) {
83-
(<any>componentView.parent).removeChild(componentView);
84-
}
85-
86-
page.content = componentView;
87-
parentPage.showModal(page, options.context, closeCallback, options.fullscreen);
88-
});
89-
}
90-
}
91-
92-
93-
@Directive({
94-
selector: "[modal-dialog-host]" // tslint:disable-line:directive-selector
95-
})
96-
export class ModalDialogHost { // tslint:disable-line:directive-class-suffix
97-
constructor() {
98-
throw new Error("ModalDialogHost is deprecated. Call ModalDialogService.showModal() " +
99-
"by passing ViewContainerRef in the options instead.");
100-
}
101-
}
1+
import {
2+
ReflectiveInjector, ComponentFactoryResolver, ViewContainerRef,
3+
Type, Injectable, ComponentRef, Directive
4+
} from "@angular/core";
5+
import { Page } from "ui/page";
6+
import { View } from "ui/core/view";
7+
import { DetachedLoader } from "../common/detached-loader";
8+
import { PageFactory, PAGE_FACTORY } from "../platform-providers";
9+
10+
export interface ModalDialogOptions {
11+
context?: any;
12+
fullscreen?: boolean;
13+
viewContainerRef?: ViewContainerRef;
14+
}
15+
16+
export class ModalDialogParams {
17+
constructor(
18+
public context: any = {},
19+
public closeCallback: (...args) => any) {
20+
}
21+
}
22+
23+
@Injectable()
24+
export class ModalDialogService {
25+
public showModal(type: Type<any>, options: ModalDialogOptions): Promise<any> {
26+
if (!options.viewContainerRef) {
27+
throw new Error(
28+
"No viewContainerRef: Make sure you pass viewContainerRef in ModalDialogOptions.");
29+
}
30+
31+
const viewContainerRef = options.viewContainerRef;
32+
const parentPage: Page = viewContainerRef.injector.get(Page);
33+
const resolver: ComponentFactoryResolver = viewContainerRef.injector.get(
34+
ComponentFactoryResolver);
35+
const pageFactory: PageFactory = viewContainerRef.injector.get(PAGE_FACTORY);
36+
37+
return new Promise((resolve) => {
38+
setTimeout(() => ModalDialogService.showDialog(
39+
type,
40+
options,
41+
resolve,
42+
viewContainerRef,
43+
resolver,
44+
parentPage,
45+
pageFactory
46+
), 10);
47+
});
48+
}
49+
50+
private static showDialog(
51+
type: Type<any>,
52+
options: ModalDialogOptions,
53+
doneCallback,
54+
containerRef: ViewContainerRef,
55+
resolver: ComponentFactoryResolver,
56+
parentPage: Page,
57+
pageFactory: PageFactory): void {
58+
59+
const page = pageFactory({ isModal: true, componentType: type });
60+
61+
let detachedLoaderRef: ComponentRef<DetachedLoader>;
62+
const closeCallback = (...args) => {
63+
doneCallback.apply(undefined, args);
64+
page.closeModal();
65+
detachedLoaderRef.instance.detectChanges();
66+
detachedLoaderRef.destroy();
67+
};
68+
69+
const modalParams = new ModalDialogParams(options.context, closeCallback);
70+
71+
const providers = ReflectiveInjector.resolve([
72+
{ provide: Page, useValue: page },
73+
{ provide: ModalDialogParams, useValue: modalParams },
74+
]);
75+
76+
const childInjector = ReflectiveInjector.fromResolvedProviders(
77+
providers, containerRef.parentInjector);
78+
const detachedFactory = resolver.resolveComponentFactory(DetachedLoader);
79+
detachedLoaderRef = containerRef.createComponent(detachedFactory, -1, childInjector, null);
80+
detachedLoaderRef.instance.loadComponent(type).then((compRef) => {
81+
const componentView = <View>compRef.location.nativeElement;
82+
83+
if (componentView.parent) {
84+
(<any>componentView.parent).removeChild(componentView);
85+
}
86+
87+
page.content = componentView;
88+
parentPage.showModal(page, options.context, closeCallback, options.fullscreen);
89+
});
90+
}
91+
}
92+
93+
94+
@Directive({
95+
selector: "[modal-dialog-host]" // tslint:disable-line:directive-selector
96+
})
97+
export class ModalDialogHost { // tslint:disable-line:directive-class-suffix
98+
constructor() {
99+
throw new Error("ModalDialogHost is deprecated. Call ModalDialogService.showModal() " +
100+
"by passing ViewContainerRef in the options instead.");
101+
}
102+
}

0 commit comments

Comments
 (0)