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 {bind, Injector} from 'angular2/di'; | ||||
| import { | ||||
|   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 {isPresent, Type} from 'angular2/src/facade/lang'; | ||||
| import {DOM} from 'angular2/src/dom/dom_adapter'; | ||||
| import {MouseEvent, KeyboardEvent} from 'angular2/src/facade/browser'; | ||||
| 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): body scrolling is disabled while dialog is open.
 | ||||
| // 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): Animate dialog out of / into opening element.
 | ||||
| 
 | ||||
| var _nextDialogId = 0; | ||||
| 
 | ||||
| /** | ||||
|  * Service for opening modal dialogs. | ||||
|  */ | ||||
| @Injectable() | ||||
| export class MdDialog { | ||||
|   componentLoader: DynamicComponentLoader; | ||||
|   domRenderer: DomRenderer; | ||||
| @ -39,13 +42,12 @@ export class MdDialog { | ||||
|    * Opens a modal dialog. | ||||
|    * @param type The component to open. | ||||
|    * @param elementRef The logical location into which the component will be opened. | ||||
|    * @param parentInjector | ||||
|    * @param options | ||||
|    * @returns Promise for a reference to the dialog. | ||||
|    */ | ||||
|   open( | ||||
|       type: Type, | ||||
|       elementRef: ElementRef, | ||||
|       parentInjector: Injector, | ||||
|       options: MdDialogConfig = null): Promise<MdDialogRef> { | ||||
|   open(type: Type, elementRef: ElementRef, parentInjector: Injector, | ||||
|        options: MdDialogConfig = null): Promise<MdDialogRef> { | ||||
|     var config = isPresent(options) ? options : new MdDialogConfig(); | ||||
| 
 | ||||
|     // 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); | ||||
| 
 | ||||
|     // First, load the MdDialogContainer, into which the given component will be loaded.
 | ||||
|     return this.componentLoader.loadIntoNewLocation( | ||||
|         MdDialogContainer, elementRef).then(containerRef => { | ||||
|       // TODO(tbosch): clean this up when we have custom renderers (https://github.com/angular/angular/issues/1807)
 | ||||
|       // TODO(jelbourn): Don't use direct DOM access. Need abstraction to create an element
 | ||||
|       // directly on the document body (also needed for web workers stuff).
 | ||||
|       // Create a DOM node to serve as a physical host element for the dialog.
 | ||||
|       var dialogElement = this.domRenderer.getHostElement(containerRef.hostView.render); | ||||
|       DOM.appendChild(DOM.query('body'), dialogElement); | ||||
|     return this.componentLoader.loadIntoNewLocation(MdDialogContainer, elementRef) | ||||
|         .then(containerRef => { | ||||
|           // TODO(tbosch): clean this up when we have custom renderers
 | ||||
|           // (https://github.com/angular/angular/issues/1807)
 | ||||
|           // TODO(jelbourn): Don't use direct DOM access. Need abstraction to create an element
 | ||||
|           // directly on the document body (also needed for web workers stuff).
 | ||||
|           // Create a DOM node to serve as a physical host element for the dialog.
 | ||||
|           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.
 | ||||
|       // Configure properties on the host element.
 | ||||
|       DOM.addClass(dialogElement, 'md-dialog'); | ||||
|       DOM.setAttribute(dialogElement, 'tabindex', '0'); | ||||
|           // TODO(jelbourn): Use hostProperties binding to set these once #1539 is fixed.
 | ||||
|           // Configure properties on the host element.
 | ||||
|           DOM.addClass(dialogElement, 'md-dialog'); | ||||
|           DOM.setAttribute(dialogElement, 'tabindex', '0'); | ||||
| 
 | ||||
|       // TODO(jelbourn): Do this with hostProperties (or another rendering abstraction) once ready.
 | ||||
|       if (isPresent(config.width)) { | ||||
|         DOM.setStyle(dialogElement, 'width', config.width); | ||||
|       } | ||||
|       if (isPresent(config.height)) { | ||||
|         DOM.setStyle(dialogElement, 'height', config.height); | ||||
|       } | ||||
|           // TODO(jelbourn): Do this with hostProperties (or another rendering abstraction) once
 | ||||
|           // ready.
 | ||||
|           if (isPresent(config.width)) { | ||||
|             DOM.setStyle(dialogElement, 'width', config.width); | ||||
|           } | ||||
|           if (isPresent(config.height)) { | ||||
|             DOM.setStyle(dialogElement, 'height', config.height); | ||||
|           } | ||||
| 
 | ||||
|       dialogRef.containerRef = containerRef; | ||||
|           dialogRef.containerRef = containerRef; | ||||
| 
 | ||||
|       // Now load the given component into the MdDialogContainer.
 | ||||
|       return this.componentLoader.loadNextToExistingLocation( | ||||
|           type, containerRef.instance.contentRef, contentInjector).then(contentRef => { | ||||
|           // Now load the given component into the MdDialogContainer.
 | ||||
|           return this.componentLoader.loadNextToExistingLocation( | ||||
|                                          type, containerRef.instance.contentRef, contentInjector) | ||||
|               .then(contentRef => { | ||||
| 
 | ||||
|         // 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
 | ||||
|         // opener.
 | ||||
|         dialogRef.contentRef = contentRef; | ||||
|         containerRef.instance.dialogRef = dialogRef; | ||||
|                 // 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
 | ||||
|                 // opener.
 | ||||
|                 dialogRef.contentRef = contentRef; | ||||
|                 containerRef.instance.dialogRef = dialogRef; | ||||
| 
 | ||||
|         backdropRefPromise.then(backdropRef => { | ||||
|           dialogRef.whenClosed.then((_) => { | ||||
|             backdropRef.dispose(); | ||||
|           }); | ||||
|                 backdropRefPromise.then(backdropRef => { | ||||
|                   dialogRef.whenClosed.then((_) => { backdropRef.dispose(); }); | ||||
|                 }); | ||||
| 
 | ||||
|                 return dialogRef; | ||||
|               }); | ||||
|         }); | ||||
| 
 | ||||
|         return dialogRef; | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   /** Loads the dialog backdrop (transparent overlay over the rest of the page). */ | ||||
|   _openBackdrop(elementRef:ElementRef, injector: Injector): Promise<ComponentRef> { | ||||
|     return this.componentLoader.loadIntoNewLocation( | ||||
|         MdBackdrop, elementRef, injector).then( (componentRef) => { | ||||
|       // TODO(tbosch): clean this up when we have custom renderers (https://github.com/angular/angular/issues/1807)
 | ||||
|       var backdropElement = this.domRenderer.getHostElement(componentRef.hostView.render); | ||||
|       DOM.addClass(backdropElement, 'md-backdrop'); | ||||
|       DOM.appendChild(DOM.query('body'), backdropElement); | ||||
|       return componentRef; | ||||
|     }); | ||||
|   _openBackdrop(elementRef: ElementRef, injector: Injector): Promise<ComponentRef> { | ||||
|     return this.componentLoader.loadIntoNewLocation(MdBackdrop, elementRef, injector) | ||||
|         .then((componentRef) => { | ||||
|           // TODO(tbosch): clean this up when we have custom renderers
 | ||||
|           // (https://github.com/angular/angular/issues/1807)
 | ||||
|           var backdropElement = this.domRenderer.getHostElement(componentRef.hostView.render); | ||||
|           DOM.addClass(backdropElement, 'md-backdrop'); | ||||
|           DOM.appendChild(DOM.query('body'), backdropElement); | ||||
|           return componentRef; | ||||
|         }); | ||||
|   } | ||||
| 
 | ||||
|   alert(message: string, okMessage: string): Promise { | ||||
| @ -163,8 +167,10 @@ export class MdDialogRef { | ||||
|       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 constructor of the very instance they are trying to get (which is much more easily accessed as `this`).
 | ||||
|     // The only time one could attempt to access this property before the value is set is if an
 | ||||
|     // 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."; | ||||
|   } | ||||
| 
 | ||||
| @ -203,13 +209,11 @@ export class MdDialogConfig { | ||||
|  */ | ||||
| @Component({ | ||||
|   selector: 'md-dialog-container', | ||||
|   hostListeners: { | ||||
|     'body:^keydown': 'documentKeypress($event)' | ||||
|   } | ||||
|   hostListeners: {'body:^keydown': 'documentKeypress($event)'}, | ||||
| }) | ||||
| @View({ | ||||
|   templateUrl: 'angular2_material/src/components/dialog/dialog.html', | ||||
|   directives: [MdDialogContent] | ||||
|   directives: [FORWARD_REF(() => MdDialogContent)] | ||||
| }) | ||||
| class MdDialogContainer { | ||||
|   // 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({ | ||||
|   selector: 'md-backdrop', | ||||
|   hostListeners: { | ||||
|     'click': 'onClick()' | ||||
|   } | ||||
|   hostListeners: {'click': 'onClick()'}, | ||||
| }) | ||||
| @View({template: ''}) | ||||
| class MdBackdrop { | ||||
| @ -256,15 +269,3 @@ class MdBackdrop { | ||||
|     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 {MdDialog, MdDialogRef, MdDialogConfig} from 'angular2_material/src/components/dialog/dialog' | ||||
| import {bootstrap, ElementRef, ComponentRef, Component, View} from 'angular2/angular2'; | ||||
| import { | ||||
|   MdDialog, | ||||
|   MdDialogRef, | ||||
|   MdDialogConfig | ||||
| } from 'angular2_material/src/components/dialog/dialog'; | ||||
| import {UrlResolver} from 'angular2/src/services/url_resolver'; | ||||
| import {commonDemoSetup, DemoUrlResolver} from '../demo_common'; | ||||
| import {bind, Injector} from 'angular2/di'; | ||||
| 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({ | ||||
|   selector: 'demo-app', | ||||
|   appInjector: [MdDialog] | ||||
|   appInjector: [MdDialog], | ||||
| }) | ||||
| @View({ | ||||
|   templateUrl: './demo_app.html', | ||||
|   directives: [] | ||||
|   directives: [], | ||||
| }) | ||||
| class DemoApp { | ||||
|   dialog: MdDialog; | ||||
| @ -43,16 +42,16 @@ class DemoApp { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     this.dialog.open(SimpleDialogComponent, | ||||
|         this.elementRef, this.injector, this.dialogConfig).then(ref => { | ||||
|       this.dialogRef = ref; | ||||
|       ref.instance.numCoconuts = 777; | ||||
|     this.dialog.open(SimpleDialogComponent, this.elementRef, this.injector, this.dialogConfig) | ||||
|         .then(ref => { | ||||
|           this.dialogRef = ref; | ||||
|           ref.instance.numCoconuts = 777; | ||||
| 
 | ||||
|       ref.whenClosed.then(result => { | ||||
|         this.dialogRef = null; | ||||
|         this.lastResult = result; | ||||
|       }); | ||||
|     }); | ||||
|           ref.whenClosed.then(result => { | ||||
|             this.dialogRef = null; | ||||
|             this.lastResult = result; | ||||
|           }); | ||||
|         }); | ||||
|   } | ||||
| 
 | ||||
|   close() { | ||||
| @ -62,7 +61,7 @@ class DemoApp { | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'simple-dialog', | ||||
|   properties: ['numCoconuts'] | ||||
|   properties: ['numCoconuts'], | ||||
| }) | ||||
| @View({ | ||||
|   template: ` | ||||
| @ -70,7 +69,7 @@ class DemoApp { | ||||
|     <p>There are {{numCoconuts}} coconuts.</p> | ||||
|     <p>Return: <input (input)="updateValue($event)"></p> | ||||
|     <button type="button" (click)="done()">Done</button> | ||||
|   ` | ||||
|   `,
 | ||||
| }) | ||||
| class SimpleDialogComponent { | ||||
|   numCoconuts: number; | ||||
| @ -95,9 +94,5 @@ class SimpleDialogComponent { | ||||
| 
 | ||||
| export function main() { | ||||
|   commonDemoSetup(); | ||||
|   bootstrap(DemoApp, [ | ||||
|     bind(UrlResolver).toValue(new DemoUrlResolver()) | ||||
|   ]); | ||||
|   bootstrap(DemoApp, [bind(UrlResolver).toValue(new DemoUrlResolver())]); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user