Skip to content

Modal dialog service #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 24, 2016
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
3 changes: 2 additions & 1 deletion ng-sample/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {ListTestAsync} from "./examples/list/list-test-async";
import {ImageTest} from "./examples/image/image-test";
import {NavigationTest} from "./examples/navigation/navigation-test";
import {ActionBarTest} from "./examples/action-bar/action-bar-test";

import {ModalTest} from "./examples/modal/modal-test";

nativeScriptBootstrap(RendererTest);
//nativeScriptBootstrap(Benchmark);
Expand All @@ -35,3 +35,4 @@ nativeScriptBootstrap(RendererTest);
//nativeScriptBootstrap(ImageTest);
//nativeScriptBootstrap(NavigationTest, [NS_ROUTER_PROVIDERS]);
//nativeScriptBootstrap(ActionBarTest, [NS_ROUTER_PROVIDERS], { startPageActionBarHidden: false });
// nativeScriptBootstrap(ModalTest);
4 changes: 2 additions & 2 deletions ng-sample/app/examples/action-bar/action-bar-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class FirstComponent {


@Component({
selector: "nested-componenet",
selector: "nested-component",
directives: [NS_ROUTER_DIRECTIVES, NS_DIRECTIVES],
template: `

Expand Down Expand Up @@ -65,7 +65,7 @@ class NestedComponent {

<StackLayout verticalAlignment="center">
<Label text="Second Page is Here" class="title"></Label>
<nested-componenet></nested-componenet>
<nested-component></nested-component>
</StackLayout>
`,
})
Expand Down
35 changes: 35 additions & 0 deletions ng-sample/app/examples/modal/modal-content.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {Component} from 'angular2/core';
import {ModalDialogParams} from "../../nativescript-angular/directives/dialogs";

@Component({
selector: 'modal-content',
template: `
<StackLayout margin="24" horizontalAlignment="center" verticalAlignment="center">
<Label [text]="prompt"></Label>
<StackLayout orientation="horizontal" marginTop="12">
<Button text="ok" (tap)="close('OK')"></Button>
<Button text="cancel" (tap)="close('Cancel')"></Button>
</StackLayout>
</StackLayout>
`
})
export class ModalContent {
public prompt: string;
constructor(private params: ModalDialogParams) {
console.log("ModalContent.constructor: " + JSON.stringify(params))
this.prompt = params.context.promptMsg;
}

public close(res: string) {
this.params.closeCallback(res);
}

ngOnInit() {
console.log("ModalContent.ngOnInit");

}

ngOnDestroy() {
console.log("ModalContent.ngOnDestroy");
}
}
104 changes: 104 additions & 0 deletions ng-sample/app/examples/modal/modal-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {Component} from 'angular2/core';
import * as dialogs from "ui/dialogs";
import {ModalDialogService, ModalDialogOptions, ModalDialogHost} from "../../nativescript-angular/directives/dialogs";
import {ModalContent} from "./modal-content";

@Component({
selector: 'modal-test',
directives: [ModalDialogHost],
providers: [ModalDialogService],
template: `
<GridLayout rows="*, auto" modal-dialog-host>
<StackLayout verticalAlignment="top" margin="12">
<Button text="show component" (tap)="showModal(false)"></Button>
<Button text="show component fullscreen" (tap)="showModal(true)"></Button>

<Button text="alert" (tap)="showAlert()"></Button>
<Button text="confirm" (tap)="showConfirm()"></Button>
<Button text="prompt" (tap)="showPrompt()"></Button>

<Button text="action" (tap)="showAction()"></Button>
<Button text="login" (tap)="showLogin()"></Button>
</StackLayout>

<Label [text]="'RESULT: ' + result" row="1" margin="12"></Label>
</GridLayout>
`
})
export class ModalTest {
public result: string = "result";

constructor(private modal: ModalDialogService) {
}

public showModal(fullscreen: boolean) {
var options: ModalDialogOptions = {
context: { promptMsg: "This is the prompt message!" },
fullscreen: fullscreen
};

this.modal.showModal(ModalContent, options).then((res: string) => {
this.result = res || "empty result";
})
}

public showAlert() {
dialogs.alert({
title: "Alert Title",
message: "The name will change.",
okButtonText: "OK"
}).then(() => {
this.result = "alert closed";
});
}

public showConfirm() {
dialogs.confirm({
title: "Name",
message: "Do you want to change the name?",
cancelButtonText: "No",
neutralButtonText: "Ignore",
okButtonText: "Yes"
}).then((confirmResult) => {
this.result = confirmResult + "";
});
}

public showPrompt() {
dialogs.prompt({
title: "Name",
message: "Enter name:",
cancelButtonText: "Cancel",
neutralButtonText: "Ignore",
okButtonText: "OK",
defaultText: "John Reese",
inputType: dialogs.inputType.text
}).then((promptResult) => {
this.result = promptResult.result ? promptResult.text : "no result";
});
}

public showAction() {
dialogs.action({
message: "Choose action:",
cancelButtonText: "Close",
actions: ["Foo", "Bar"]
}).then((actionResult) => {
this.result = actionResult;
});
}

public showLogin() {
dialogs.login({
title: "Name",
message: "Enter name:",
cancelButtonText: "Cancel",
neutralButtonText: "Ignore",
okButtonText: "OK",
userName: "John",
password: "Reese"
}).then((loginResult) => {
this.result = loginResult.result ? ("user: " + loginResult.userName + " pass: " + loginResult.password) : "no result";
});
}
}
12 changes: 6 additions & 6 deletions ng-sample/app/examples/navigation/nav-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class DetailComponent {
directives: [ROUTER_DIRECTIVES, NS_ROUTER_DIRECTIVES],
template: `
<GridLayout rows="auto, auto, auto, *" columns="*, *" margin="10" backgroundColor="lightgreen">
<Label [text]="'Componenet ID: ' + compId" colSpan="2" row="0"
<Label [text]="'Component ID: ' + compId" colSpan="2" row="0"
style="font-size: 30; horizontal-align: center"></Label>

<Label [text]="'Depth: ' + depth" colSpan="2" row="1"
Expand Down Expand Up @@ -108,29 +108,29 @@ export class NavComponent implements OnActivate, OnDeactivate {
this.compId = NavComponent.counter;
this.depth = parseInt(params.get("depth"));

console.log("NavComponent.constructor() componenetID: " + this.compId)
console.log("NavComponent.constructor() componentID: " + this.compId)
}

public goBack() {
this.location.back();
}

routerOnActivate(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction): any {
console.log("NavComponent.routerOnActivate() componenetID: " + this.compId)
console.log("NavComponent.routerOnActivate() componentID: " + this.compId)
}

routerOnDeactivate(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction): any {
console.log("NavComponent.routerOnDeactivate() componenetID: " + this.compId)
console.log("NavComponent.routerOnDeactivate() componentID: " + this.compId)
}

routerCanReuse(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction): any {
// Reuse if depth is the same.
var reuse = (prevInstruction.params["depth"] === nextInstruction.params["depth"]);
console.log("NavComponent.routerCanReuse() componenetID: " + this.compId + " return: " + reuse);
console.log("NavComponent.routerCanReuse() componentID: " + this.compId + " return: " + reuse);
return reuse;
}

routerOnReuse(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction): any {
console.log("NavComponent.routerOnReuse() componenetID: " + this.compId);
console.log("NavComponent.routerOnReuse() componentID: " + this.compId);
}
}
2 changes: 1 addition & 1 deletion ng-sample/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
},
"homepage": "https://github.com/NativeScript/template-hello-world",
"dependencies": {
"tns-core-modules": "^2.0.0-angular-0",
"tns-core-modules": "^2.0.0-angular-1",
"angular2": "2.0.0-beta.9",
"parse5": "1.4.2",
"punycode": "1.3.2",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
"scripts": {},
"dependencies": {
"tns-core-modules": "^2.0.0-angular-0",
"tns-core-modules": "^2.0.0-angular-1",
"angular2": "2.0.0-beta.9",
"es6-shim": "^0.33.3",
"parse5": "1.4.2",
Expand Down
21 changes: 21 additions & 0 deletions src/nativescript-angular/common/detached-loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {DynamicComponentLoader, ComponentRef, ElementRef, Component, Type} from 'angular2/core';

/**
* Wrapper component used for loading compnenets when navigating
* It uses DetachedContainer as selector so that it is elementRef is not attached to the visual tree.
*/
@Component({
selector: 'DetachedContainer',
template: `<Placeholder #loader></Placeholder>`
})
export class DetachedLoader {
constructor(
private element: ElementRef,
private loader: DynamicComponentLoader
) {
}

public loadComponent(componentType: Type): Promise<ComponentRef> {
return this.loader.loadIntoLocation(componentType, this.element, 'loader');
}
}
77 changes: 77 additions & 0 deletions src/nativescript-angular/directives/dialogs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import {DynamicComponentLoader, ElementRef, Injector, provide, Type, Injectable, ComponentRef, Directive} from 'angular2/core';
import {Page} from 'ui/page';
import {View} from 'ui/core/view';
import {DetachedLoader} from '../common/detached-loader';

export interface ModalDialogOptions {
context?: any;
fullscreen?: boolean;
}

export class ModalDialogParams {
constructor(
public context: any = {},
public closeCallback: (...args) => any) {
}
}

@Injectable()
export class ModalDialogService {
private elementRef: ElementRef;

constructor(
private page: Page,
private loader: DynamicComponentLoader) {
}

public registerElementRef(ref: ElementRef) {
this.elementRef = ref;
}

public showModal(type: Type, options: ModalDialogOptions): Promise<any> {
if (!this.elementRef) {
throw new Error("No elementRef: Make sure you have the modal-dialog-host directive inside your component.");
}
return new Promise((resove, reject) => {
const page = new Page();

var detachedLoaderRef: ComponentRef;
const closeCallback = (...args) => {
resove.apply(undefined, args);
page.closeModal();
detachedLoaderRef.dispose();
}
const modalParams = new ModalDialogParams(options.context, closeCallback);

const providers = Injector.resolve([
provide(Page, { useValue: page }),
provide(ModalDialogParams, { useValue: modalParams }),
]);

this.loader.loadNextToLocation(DetachedLoader, this.elementRef, providers)
.then((loaderRef) => {
detachedLoaderRef = loaderRef;
return (<DetachedLoader>loaderRef.instance).loadComponent(type)
})
.then((compRef) => {
//Component loaded. Find its root native view.
const componentView = <View>compRef.location.nativeElement;
if (componentView.parent) {
(<any>componentView.parent).removeChild(componentView);
}
page.content = componentView;
this.page.showModal(page, options.context, closeCallback, options.fullscreen);
});
})
}
}


@Directive({
selector: "[modal-dialog-host]"
})
export class ModalDialogHost {
constructor(elementRef: ElementRef, modalService: ModalDialogService) {
modalService.registerElementRef(elementRef);
}
}
18 changes: 18 additions & 0 deletions src/nativescript-angular/modal-dialog.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {Type} from 'angular2/core';

export interface ModalDialogOptions {
context?: any;
fullscreen?: boolean;
}

export class ModalDialogParams {
public context: any;
public closeCallback: (...args) => any;
}

export class ModalDialogService {
public showModal(type: Type, options: ModalDialogOptions): Promise<any>;
}

export class ModalDialogHost {
}
6 changes: 6 additions & 0 deletions src/nativescript-angular/modal-dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export {
ModalDialogHost,
ModalDialogOptions,
ModalDialogParams,
ModalDialogService
} from "./directives/dialogs";
Loading