chore(material): move dialog to TypeScript.
This commit is contained in:
		
							parent
							
								
									4f3acdb004
								
							
						
					
					
						commit
						c8947d77bf
					
				| @ -1,17 +1,21 @@ | |||||||
| import {DynamicComponentLoader, ElementRef, ComponentRef, onDestroy, DomRenderer} from 'angular2/angular2'; | import { | ||||||
| import {bind, Injector} from 'angular2/di'; |   Component, | ||||||
|  |   Directive, | ||||||
|  |   View, | ||||||
|  |   Parent, | ||||||
|  |   ElementRef, | ||||||
|  |   DynamicComponentLoader, | ||||||
|  |   ComponentRef, | ||||||
|  |   DomRenderer | ||||||
|  | } from 'angular2/angular2'; | ||||||
|  | import {bind, Injector, Injectable, FORWARD_REF} from 'angular2/di'; | ||||||
|  | 
 | ||||||
| import {ObservableWrapper, Promise, PromiseWrapper} from 'angular2/src/facade/async'; | import {ObservableWrapper, Promise, PromiseWrapper} from 'angular2/src/facade/async'; | ||||||
| import {isPresent, Type} from 'angular2/src/facade/lang'; | import {isPresent, Type} from 'angular2/src/facade/lang'; | ||||||
| import {DOM} from 'angular2/src/dom/dom_adapter'; | import {DOM} from 'angular2/src/dom/dom_adapter'; | ||||||
| import {MouseEvent, KeyboardEvent} from 'angular2/src/facade/browser'; | import {MouseEvent, KeyboardEvent} from 'angular2/src/facade/browser'; | ||||||
| import {KEY_ESC} from 'angular2_material/src/core/constants'; | import {KEY_ESC} from 'angular2_material/src/core/constants'; | ||||||
| 
 | 
 | ||||||
| // TODO(radokirov): Once the application is transpiled by TS instead of Traceur,
 |  | ||||||
| // add those imports back into 'angular2/angular2';
 |  | ||||||
| import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations'; |  | ||||||
| import {Parent} from 'angular2/src/core/annotations_impl/visibility'; |  | ||||||
| import {View} from 'angular2/src/core/annotations_impl/view'; |  | ||||||
| 
 |  | ||||||
| // TODO(jelbourn): Opener of dialog can control where it is rendered.
 | // TODO(jelbourn): Opener of dialog can control where it is rendered.
 | ||||||
| // TODO(jelbourn): body scrolling is disabled while dialog is open.
 | // TODO(jelbourn): body scrolling is disabled while dialog is open.
 | ||||||
| // TODO(jelbourn): Don't manually construct and configure a DOM element. See #1402
 | // TODO(jelbourn): Don't manually construct and configure a DOM element. See #1402
 | ||||||
| @ -21,11 +25,10 @@ import {View} from 'angular2/src/core/annotations_impl/view'; | |||||||
| // TODO(jelbourn): Pre-built `alert` and `confirm` dialogs.
 | // TODO(jelbourn): Pre-built `alert` and `confirm` dialogs.
 | ||||||
| // TODO(jelbourn): Animate dialog out of / into opening element.
 | // TODO(jelbourn): Animate dialog out of / into opening element.
 | ||||||
| 
 | 
 | ||||||
| var _nextDialogId = 0; |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * Service for opening modal dialogs. |  * Service for opening modal dialogs. | ||||||
|  */ |  */ | ||||||
|  | @Injectable() | ||||||
| export class MdDialog { | export class MdDialog { | ||||||
|   componentLoader: DynamicComponentLoader; |   componentLoader: DynamicComponentLoader; | ||||||
|   domRenderer: DomRenderer; |   domRenderer: DomRenderer; | ||||||
| @ -39,13 +42,12 @@ export class MdDialog { | |||||||
|    * Opens a modal dialog. |    * Opens a modal dialog. | ||||||
|    * @param type The component to open. |    * @param type The component to open. | ||||||
|    * @param elementRef The logical location into which the component will be opened. |    * @param elementRef The logical location into which the component will be opened. | ||||||
|  |    * @param parentInjector | ||||||
|  |    * @param options | ||||||
|    * @returns Promise for a reference to the dialog. |    * @returns Promise for a reference to the dialog. | ||||||
|    */ |    */ | ||||||
|   open( |   open(type: Type, elementRef: ElementRef, parentInjector: Injector, | ||||||
|       type: Type, |        options: MdDialogConfig = null): Promise<MdDialogRef> { | ||||||
|       elementRef: ElementRef, |  | ||||||
|       parentInjector: Injector, |  | ||||||
|       options: MdDialogConfig = null): Promise<MdDialogRef> { |  | ||||||
|     var config = isPresent(options) ? options : new MdDialogConfig(); |     var config = isPresent(options) ? options : new MdDialogConfig(); | ||||||
| 
 | 
 | ||||||
|     // Create the dialogRef here so that it can be injected into the content component.
 |     // Create the dialogRef here so that it can be injected into the content component.
 | ||||||
| @ -57,61 +59,63 @@ export class MdDialog { | |||||||
|     var backdropRefPromise = this._openBackdrop(elementRef, contentInjector); |     var backdropRefPromise = this._openBackdrop(elementRef, contentInjector); | ||||||
| 
 | 
 | ||||||
|     // First, load the MdDialogContainer, into which the given component will be loaded.
 |     // First, load the MdDialogContainer, into which the given component will be loaded.
 | ||||||
|     return this.componentLoader.loadIntoNewLocation( |     return this.componentLoader.loadIntoNewLocation(MdDialogContainer, elementRef) | ||||||
|         MdDialogContainer, elementRef).then(containerRef => { |         .then(containerRef => { | ||||||
|       // TODO(tbosch): clean this up when we have custom renderers (https://github.com/angular/angular/issues/1807)
 |           // TODO(tbosch): clean this up when we have custom renderers
 | ||||||
|       // TODO(jelbourn): Don't use direct DOM access. Need abstraction to create an element
 |           // (https://github.com/angular/angular/issues/1807)
 | ||||||
|       // directly on the document body (also needed for web workers stuff).
 |           // TODO(jelbourn): Don't use direct DOM access. Need abstraction to create an element
 | ||||||
|       // Create a DOM node to serve as a physical host element for the dialog.
 |           // directly on the document body (also needed for web workers stuff).
 | ||||||
|       var dialogElement = this.domRenderer.getHostElement(containerRef.hostView.render); |           // Create a DOM node to serve as a physical host element for the dialog.
 | ||||||
|       DOM.appendChild(DOM.query('body'), dialogElement); |           var dialogElement = this.domRenderer.getHostElement(containerRef.hostView.render); | ||||||
|  |           DOM.appendChild(DOM.query('body'), dialogElement); | ||||||
| 
 | 
 | ||||||
|       // TODO(jelbourn): Use hostProperties binding to set these once #1539 is fixed.
 |           // TODO(jelbourn): Use hostProperties binding to set these once #1539 is fixed.
 | ||||||
|       // Configure properties on the host element.
 |           // Configure properties on the host element.
 | ||||||
|       DOM.addClass(dialogElement, 'md-dialog'); |           DOM.addClass(dialogElement, 'md-dialog'); | ||||||
|       DOM.setAttribute(dialogElement, 'tabindex', '0'); |           DOM.setAttribute(dialogElement, 'tabindex', '0'); | ||||||
| 
 | 
 | ||||||
|       // TODO(jelbourn): Do this with hostProperties (or another rendering abstraction) once ready.
 |           // TODO(jelbourn): Do this with hostProperties (or another rendering abstraction) once
 | ||||||
|       if (isPresent(config.width)) { |           // ready.
 | ||||||
|         DOM.setStyle(dialogElement, 'width', config.width); |           if (isPresent(config.width)) { | ||||||
|       } |             DOM.setStyle(dialogElement, 'width', config.width); | ||||||
|       if (isPresent(config.height)) { |           } | ||||||
|         DOM.setStyle(dialogElement, 'height', config.height); |           if (isPresent(config.height)) { | ||||||
|       } |             DOM.setStyle(dialogElement, 'height', config.height); | ||||||
|  |           } | ||||||
| 
 | 
 | ||||||
|       dialogRef.containerRef = containerRef; |           dialogRef.containerRef = containerRef; | ||||||
| 
 | 
 | ||||||
|       // Now load the given component into the MdDialogContainer.
 |           // Now load the given component into the MdDialogContainer.
 | ||||||
|       return this.componentLoader.loadNextToExistingLocation( |           return this.componentLoader.loadNextToExistingLocation( | ||||||
|           type, containerRef.instance.contentRef, contentInjector).then(contentRef => { |                                          type, containerRef.instance.contentRef, contentInjector) | ||||||
|  |               .then(contentRef => { | ||||||
| 
 | 
 | ||||||
|         // Wrap both component refs for the container and the content so that we can return
 |                 // Wrap both component refs for the container and the content so that we can return
 | ||||||
|         // the `instance` of the content but the dispose method of the container back to the
 |                 // the `instance` of the content but the dispose method of the container back to the
 | ||||||
|         // opener.
 |                 // opener.
 | ||||||
|         dialogRef.contentRef = contentRef; |                 dialogRef.contentRef = contentRef; | ||||||
|         containerRef.instance.dialogRef = dialogRef; |                 containerRef.instance.dialogRef = dialogRef; | ||||||
| 
 | 
 | ||||||
|         backdropRefPromise.then(backdropRef => { |                 backdropRefPromise.then(backdropRef => { | ||||||
|           dialogRef.whenClosed.then((_) => { |                   dialogRef.whenClosed.then((_) => { backdropRef.dispose(); }); | ||||||
|             backdropRef.dispose(); |                 }); | ||||||
|           }); | 
 | ||||||
|  |                 return dialogRef; | ||||||
|  |               }); | ||||||
|         }); |         }); | ||||||
| 
 |  | ||||||
|         return dialogRef; |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** Loads the dialog backdrop (transparent overlay over the rest of the page). */ |   /** Loads the dialog backdrop (transparent overlay over the rest of the page). */ | ||||||
|   _openBackdrop(elementRef:ElementRef, injector: Injector): Promise<ComponentRef> { |   _openBackdrop(elementRef: ElementRef, injector: Injector): Promise<ComponentRef> { | ||||||
|     return this.componentLoader.loadIntoNewLocation( |     return this.componentLoader.loadIntoNewLocation(MdBackdrop, elementRef, injector) | ||||||
|         MdBackdrop, elementRef, injector).then( (componentRef) => { |         .then((componentRef) => { | ||||||
|       // TODO(tbosch): clean this up when we have custom renderers (https://github.com/angular/angular/issues/1807)
 |           // TODO(tbosch): clean this up when we have custom renderers
 | ||||||
|       var backdropElement = this.domRenderer.getHostElement(componentRef.hostView.render); |           // (https://github.com/angular/angular/issues/1807)
 | ||||||
|       DOM.addClass(backdropElement, 'md-backdrop'); |           var backdropElement = this.domRenderer.getHostElement(componentRef.hostView.render); | ||||||
|       DOM.appendChild(DOM.query('body'), backdropElement); |           DOM.addClass(backdropElement, 'md-backdrop'); | ||||||
|       return componentRef; |           DOM.appendChild(DOM.query('body'), backdropElement); | ||||||
|     }); |           return componentRef; | ||||||
|  |         }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   alert(message: string, okMessage: string): Promise { |   alert(message: string, okMessage: string): Promise { | ||||||
| @ -163,8 +167,10 @@ export class MdDialogRef { | |||||||
|       return this._contentRef.instance; |       return this._contentRef.instance; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // The only time one could attempt to access this property before the value is set is if an access occurs during
 |     // The only time one could attempt to access this property before the value is set is if an
 | ||||||
|     // the constructor of the very instance they are trying to get (which is much more easily accessed as `this`).
 |     // access occurs during
 | ||||||
|  |     // the constructor of the very instance they are trying to get (which is much more easily
 | ||||||
|  |     // accessed as `this`).
 | ||||||
|     throw "Cannot access dialog component instance *from* that component's constructor."; |     throw "Cannot access dialog component instance *from* that component's constructor."; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -203,13 +209,11 @@ export class MdDialogConfig { | |||||||
|  */ |  */ | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'md-dialog-container', |   selector: 'md-dialog-container', | ||||||
|   hostListeners: { |   hostListeners: {'body:^keydown': 'documentKeypress($event)'}, | ||||||
|     'body:^keydown': 'documentKeypress($event)' |  | ||||||
|   } |  | ||||||
| }) | }) | ||||||
| @View({ | @View({ | ||||||
|   templateUrl: 'angular2_material/src/components/dialog/dialog.html', |   templateUrl: 'angular2_material/src/components/dialog/dialog.html', | ||||||
|   directives: [MdDialogContent] |   directives: [FORWARD_REF(() => MdDialogContent)] | ||||||
| }) | }) | ||||||
| class MdDialogContainer { | class MdDialogContainer { | ||||||
|   // Ref to the dialog content. Used by the DynamicComponentLoader to load the dialog content.
 |   // Ref to the dialog content. Used by the DynamicComponentLoader to load the dialog content.
 | ||||||
| @ -234,13 +238,22 @@ class MdDialogContainer { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Simple decorator used only to communicate an ElementRef to the parent MdDialogContainer as the | ||||||
|  |  * location | ||||||
|  |  * for where the dialog content will be loaded. | ||||||
|  |  */ | ||||||
|  | @Directive({selector: 'md-dialog-content'}) | ||||||
|  | class MdDialogContent { | ||||||
|  |   constructor(@Parent() dialogContainer: MdDialogContainer, elementRef: ElementRef) { | ||||||
|  |     dialogContainer.contentRef = elementRef; | ||||||
|  |   } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| /** Component for the dialog "backdrop", a transparent overlay over the rest of the page. */ | /** Component for the dialog "backdrop", a transparent overlay over the rest of the page. */ | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'md-backdrop', |   selector: 'md-backdrop', | ||||||
|   hostListeners: { |   hostListeners: {'click': 'onClick()'}, | ||||||
|     'click': 'onClick()' |  | ||||||
|   } |  | ||||||
| }) | }) | ||||||
| @View({template: ''}) | @View({template: ''}) | ||||||
| class MdBackdrop { | class MdBackdrop { | ||||||
| @ -256,15 +269,3 @@ class MdBackdrop { | |||||||
|     this.dialogRef.close(); |     this.dialogRef.close(); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Simple decorator used only to communicate an ElementRef to the parent MdDialogContainer as the location |  | ||||||
|  * for where the dialog content will be loaded. |  | ||||||
|  */ |  | ||||||
| @Directive({selector: 'md-dialog-content'}) |  | ||||||
| class MdDialogContent { |  | ||||||
|   constructor(@Parent() dialogContainer: MdDialogContainer, elementRef: ElementRef) { |  | ||||||
|     dialogContainer.contentRef = elementRef; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @ -1,23 +1,22 @@ | |||||||
| import {bootstrap, ElementRef, ComponentRef} from 'angular2/angular2'; | import {bootstrap, ElementRef, ComponentRef, Component, View} from 'angular2/angular2'; | ||||||
| import {MdDialog, MdDialogRef, MdDialogConfig} from 'angular2_material/src/components/dialog/dialog' | import { | ||||||
|  |   MdDialog, | ||||||
|  |   MdDialogRef, | ||||||
|  |   MdDialogConfig | ||||||
|  | } from 'angular2_material/src/components/dialog/dialog'; | ||||||
| import {UrlResolver} from 'angular2/src/services/url_resolver'; | import {UrlResolver} from 'angular2/src/services/url_resolver'; | ||||||
| import {commonDemoSetup, DemoUrlResolver} from '../demo_common'; | import {commonDemoSetup, DemoUrlResolver} from '../demo_common'; | ||||||
| import {bind, Injector} from 'angular2/di'; | import {bind, Injector} from 'angular2/di'; | ||||||
| import {isPresent} from 'angular2/src/facade/lang'; | import {isPresent} from 'angular2/src/facade/lang'; | ||||||
| 
 | 
 | ||||||
| // TODO(radokirov): Once the application is transpiled by TS instead of Traceur,
 |  | ||||||
| // add those imports back into 'angular2/angular2';
 |  | ||||||
| import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations'; |  | ||||||
| import {View} from 'angular2/src/core/annotations_impl/view'; |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'demo-app', |   selector: 'demo-app', | ||||||
|   appInjector: [MdDialog] |   appInjector: [MdDialog], | ||||||
| }) | }) | ||||||
| @View({ | @View({ | ||||||
|   templateUrl: './demo_app.html', |   templateUrl: './demo_app.html', | ||||||
|   directives: [] |   directives: [], | ||||||
| }) | }) | ||||||
| class DemoApp { | class DemoApp { | ||||||
|   dialog: MdDialog; |   dialog: MdDialog; | ||||||
| @ -43,16 +42,16 @@ class DemoApp { | |||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.dialog.open(SimpleDialogComponent, |     this.dialog.open(SimpleDialogComponent, this.elementRef, this.injector, this.dialogConfig) | ||||||
|         this.elementRef, this.injector, this.dialogConfig).then(ref => { |         .then(ref => { | ||||||
|       this.dialogRef = ref; |           this.dialogRef = ref; | ||||||
|       ref.instance.numCoconuts = 777; |           ref.instance.numCoconuts = 777; | ||||||
| 
 | 
 | ||||||
|       ref.whenClosed.then(result => { |           ref.whenClosed.then(result => { | ||||||
|         this.dialogRef = null; |             this.dialogRef = null; | ||||||
|         this.lastResult = result; |             this.lastResult = result; | ||||||
|       }); |           }); | ||||||
|     }); |         }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   close() { |   close() { | ||||||
| @ -62,7 +61,7 @@ class DemoApp { | |||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'simple-dialog', |   selector: 'simple-dialog', | ||||||
|   properties: ['numCoconuts'] |   properties: ['numCoconuts'], | ||||||
| }) | }) | ||||||
| @View({ | @View({ | ||||||
|   template: ` |   template: ` | ||||||
| @ -70,7 +69,7 @@ class DemoApp { | |||||||
|     <p>There are {{numCoconuts}} coconuts.</p> |     <p>There are {{numCoconuts}} coconuts.</p> | ||||||
|     <p>Return: <input (input)="updateValue($event)"></p> |     <p>Return: <input (input)="updateValue($event)"></p> | ||||||
|     <button type="button" (click)="done()">Done</button> |     <button type="button" (click)="done()">Done</button> | ||||||
|   ` |   `,
 | ||||||
| }) | }) | ||||||
| class SimpleDialogComponent { | class SimpleDialogComponent { | ||||||
|   numCoconuts: number; |   numCoconuts: number; | ||||||
| @ -95,9 +94,5 @@ class SimpleDialogComponent { | |||||||
| 
 | 
 | ||||||
| export function main() { | export function main() { | ||||||
|   commonDemoSetup(); |   commonDemoSetup(); | ||||||
|   bootstrap(DemoApp, [ |   bootstrap(DemoApp, [bind(UrlResolver).toValue(new DemoUrlResolver())]); | ||||||
|     bind(UrlResolver).toValue(new DemoUrlResolver()) |  | ||||||
|   ]); |  | ||||||
| } | } | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user