| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  | import { | 
					
						
							|  |  |  |   ChangeDetectorRef, | 
					
						
							|  |  |  |   Injector, | 
					
						
							|  |  |  |   OnChanges, | 
					
						
							| 
									
										
										
										
											2016-04-13 17:05:17 -07:00
										 |  |  |   ComponentFactory, | 
					
						
							|  |  |  |   ComponentRef, | 
					
						
							| 
									
										
										
										
											2016-04-14 12:35:24 -07:00
										 |  |  |   SimpleChange, | 
					
						
							| 
									
										
										
										
											2016-05-09 15:45:04 -07:00
										 |  |  |   SimpleChanges, | 
					
						
							| 
									
										
										
										
											2016-06-01 14:58:11 -07:00
										 |  |  |   ReflectiveInjector, | 
					
						
							|  |  |  |   EventEmitter | 
					
						
							| 
									
										
										
										
											2016-04-28 17:50:03 -07:00
										 |  |  | } from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | import {NG1_SCOPE} from './constants'; | 
					
						
							|  |  |  | import {ComponentInfo} from './metadata'; | 
					
						
							| 
									
										
										
										
											2015-10-26 20:17:46 -07:00
										 |  |  | import * as angular from './angular_js'; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | const INITIAL_VALUE = { | 
					
						
							|  |  |  |   __UNINITIALIZED__: true | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-12 21:32:41 -07:00
										 |  |  | export class DowngradeNg2ComponentAdapter { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   component: any = null; | 
					
						
							|  |  |  |   inputChangeCount: number = 0; | 
					
						
							| 
									
										
										
										
											2016-05-09 15:45:04 -07:00
										 |  |  |   inputChanges: SimpleChanges = null; | 
					
						
							| 
									
										
										
										
											2016-04-30 10:52:04 -07:00
										 |  |  |   componentRef: ComponentRef<any> = null; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   changeDetector: ChangeDetectorRef = null; | 
					
						
							|  |  |  |   componentScope: angular.IScope; | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |   childNodes: Node[]; | 
					
						
							| 
									
										
										
										
											2015-12-02 10:35:51 -08:00
										 |  |  |   contentInsertionPoint: Node = null; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |   constructor(private id: string, private info: ComponentInfo, | 
					
						
							|  |  |  |               private element: angular.IAugmentedJQuery, private attrs: angular.IAttributes, | 
					
						
							|  |  |  |               private scope: angular.IScope, private parentInjector: Injector, | 
					
						
							| 
									
										
										
										
											2016-04-30 10:52:04 -07:00
										 |  |  |               private parse: angular.IParseService, | 
					
						
							|  |  |  |               private componentFactory: ComponentFactory<any>) { | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |     (<any>this.element[0]).id = id; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     this.componentScope = scope.$new(); | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |     this.childNodes = <Node[]><any>element.contents(); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bootstrapNg2() { | 
					
						
							| 
									
										
										
										
											2016-04-14 12:35:24 -07:00
										 |  |  |     var childInjector = ReflectiveInjector.resolveAndCreate( | 
					
						
							| 
									
										
										
										
											2016-06-02 17:30:40 -07:00
										 |  |  |         [{provide: NG1_SCOPE, useValue: this.componentScope}], this.parentInjector); | 
					
						
							| 
									
										
										
										
											2015-12-02 10:35:51 -08:00
										 |  |  |     this.contentInsertionPoint = document.createComment('ng1 insertion point'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-13 17:05:17 -07:00
										 |  |  |     this.componentRef = | 
					
						
							| 
									
										
										
										
											2016-05-17 15:55:53 -07:00
										 |  |  |         this.componentFactory.create(childInjector, [[this.contentInsertionPoint]], this.element[0]); | 
					
						
							| 
									
										
										
										
											2016-04-13 17:05:17 -07:00
										 |  |  |     this.changeDetector = this.componentRef.changeDetectorRef; | 
					
						
							|  |  |  |     this.component = this.componentRef.instance; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-26 20:17:46 -07:00
										 |  |  |   setupInputs(): void { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     var attrs = this.attrs; | 
					
						
							|  |  |  |     var inputs = this.info.inputs; | 
					
						
							|  |  |  |     for (var i = 0; i < inputs.length; i++) { | 
					
						
							|  |  |  |       var input = inputs[i]; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |       var expr: any /** TODO #9100 */ = null; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       if (attrs.hasOwnProperty(input.attr)) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |         var observeFn = ((prop: any /** TODO #9100 */) => { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |           var prevValue = INITIAL_VALUE; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |           return (value: any /** TODO #9100 */) => { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |             if (this.inputChanges !== null) { | 
					
						
							|  |  |  |               this.inputChangeCount++; | 
					
						
							|  |  |  |               this.inputChanges[prop] = | 
					
						
							|  |  |  |                   new Ng1Change(value, prevValue === INITIAL_VALUE ? value : prevValue); | 
					
						
							|  |  |  |               prevValue = value; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             this.component[prop] = value; | 
					
						
							| 
									
										
										
										
											2015-10-26 20:17:46 -07:00
										 |  |  |           }; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |         })(input.prop); | 
					
						
							|  |  |  |         attrs.$observe(input.attr, observeFn); | 
					
						
							|  |  |  |       } else if (attrs.hasOwnProperty(input.bindAttr)) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |         expr = (attrs as any /** TODO #9100 */)[input.bindAttr]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       } else if (attrs.hasOwnProperty(input.bracketAttr)) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |         expr = (attrs as any /** TODO #9100 */)[input.bracketAttr]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       } else if (attrs.hasOwnProperty(input.bindonAttr)) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |         expr = (attrs as any /** TODO #9100 */)[input.bindonAttr]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       } else if (attrs.hasOwnProperty(input.bracketParenAttr)) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |         expr = (attrs as any /** TODO #9100 */)[input.bracketParenAttr]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |       if (expr != null) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |         var watchFn = ((prop: any /** TODO #9100 */) => (value: any /** TODO #9100 */, prevValue: any /** TODO #9100 */) => { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |           if (this.inputChanges != null) { | 
					
						
							|  |  |  |             this.inputChangeCount++; | 
					
						
							|  |  |  |             this.inputChanges[prop] = new Ng1Change(prevValue, value); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           this.component[prop] = value; | 
					
						
							|  |  |  |         })(input.prop); | 
					
						
							|  |  |  |         this.componentScope.$watch(expr, watchFn); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var prototype = this.info.type.prototype; | 
					
						
							| 
									
										
											  
											
												refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
 * onInit
 * onDestroy
 * doCheck
 * onChanges
 * afterContentInit
 * afterContentChecked
 * afterViewInit
 * afterViewChecked
 * _Router Hooks_
 * onActivate
 * onReuse
 * onDeactivate
 * canReuse
 * canDeactivate
To:
 * ngOnInit,
 * ngOnDestroy,
 * ngDoCheck,
 * ngOnChanges,
 * ngAfterContentInit,
 * ngAfterContentChecked,
 * ngAfterViewInit,
 * ngAfterViewChecked
 * _Router Hooks_
 * routerOnActivate
 * routerOnReuse
 * routerOnDeactivate
 * routerCanReuse
 * routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
											
										 
											2015-11-16 17:04:36 -08:00
										 |  |  |     if (prototype && (<OnChanges>prototype).ngOnChanges) { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       // Detect: OnChanges interface
 | 
					
						
							|  |  |  |       this.inputChanges = {}; | 
					
						
							|  |  |  |       this.componentScope.$watch(() => this.inputChangeCount, () => { | 
					
						
							|  |  |  |         var inputChanges = this.inputChanges; | 
					
						
							|  |  |  |         this.inputChanges = {}; | 
					
						
							| 
									
										
											  
											
												refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
 * onInit
 * onDestroy
 * doCheck
 * onChanges
 * afterContentInit
 * afterContentChecked
 * afterViewInit
 * afterViewChecked
 * _Router Hooks_
 * onActivate
 * onReuse
 * onDeactivate
 * canReuse
 * canDeactivate
To:
 * ngOnInit,
 * ngOnDestroy,
 * ngDoCheck,
 * ngOnChanges,
 * ngAfterContentInit,
 * ngAfterContentChecked,
 * ngAfterViewInit,
 * ngAfterViewChecked
 * _Router Hooks_
 * routerOnActivate
 * routerOnReuse
 * routerOnDeactivate
 * routerCanReuse
 * routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
											
										 
											2015-11-16 17:04:36 -08:00
										 |  |  |         (<OnChanges>this.component).ngOnChanges(inputChanges); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |     this.componentScope.$watch(() => this.changeDetector && this.changeDetector.detectChanges()); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |   projectContent() { | 
					
						
							|  |  |  |     var childNodes = this.childNodes; | 
					
						
							| 
									
										
										
										
											2015-12-02 10:35:51 -08:00
										 |  |  |     var parent = this.contentInsertionPoint.parentNode; | 
					
						
							|  |  |  |     if (parent) { | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |       for (var i = 0, ii = childNodes.length; i < ii; i++) { | 
					
						
							| 
									
										
										
										
											2015-12-02 10:35:51 -08:00
										 |  |  |         parent.insertBefore(childNodes[i], this.contentInsertionPoint); | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   setupOutputs() { | 
					
						
							|  |  |  |     var attrs = this.attrs; | 
					
						
							|  |  |  |     var outputs = this.info.outputs; | 
					
						
							|  |  |  |     for (var j = 0; j < outputs.length; j++) { | 
					
						
							|  |  |  |       var output = outputs[j]; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |       var expr: any /** TODO #9100 */ = null; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       var assignExpr = false; | 
					
						
							| 
									
										
										
										
											2015-10-10 19:56:22 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       var bindonAttr = | 
					
						
							|  |  |  |           output.bindonAttr ? output.bindonAttr.substring(0, output.bindonAttr.length - 6) : null; | 
					
						
							| 
									
										
										
										
											2016-04-12 09:40:37 -07:00
										 |  |  |       var bracketParenAttr = | 
					
						
							|  |  |  |           output.bracketParenAttr ? | 
					
						
							|  |  |  |               `[(${output.bracketParenAttr.substring(2, output.bracketParenAttr.length - 8)})]` : | 
					
						
							|  |  |  |               null; | 
					
						
							| 
									
										
										
										
											2015-10-10 19:56:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       if (attrs.hasOwnProperty(output.onAttr)) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |         expr = (attrs as any /** TODO #9100 */)[output.onAttr]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       } else if (attrs.hasOwnProperty(output.parenAttr)) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |         expr = (attrs as any /** TODO #9100 */)[output.parenAttr]; | 
					
						
							| 
									
										
										
										
											2015-10-10 19:56:22 -07:00
										 |  |  |       } else if (attrs.hasOwnProperty(bindonAttr)) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |         expr = (attrs as any /** TODO #9100 */)[bindonAttr]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |         assignExpr = true; | 
					
						
							| 
									
										
										
										
											2015-10-10 19:56:22 -07:00
										 |  |  |       } else if (attrs.hasOwnProperty(bracketParenAttr)) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |         expr = (attrs as any /** TODO #9100 */)[bracketParenAttr]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |         assignExpr = true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (expr != null && assignExpr != null) { | 
					
						
							|  |  |  |         var getter = this.parse(expr); | 
					
						
							|  |  |  |         var setter = getter.assign; | 
					
						
							|  |  |  |         if (assignExpr && !setter) { | 
					
						
							|  |  |  |           throw new Error(`Expression '${expr}' is not assignable!`); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-06-01 14:58:11 -07:00
										 |  |  |         var emitter = this.component[output.prop] as EventEmitter<any>; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |         if (emitter) { | 
					
						
							| 
									
										
										
										
											2015-10-24 18:48:43 -07:00
										 |  |  |           emitter.subscribe({ | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |             next: assignExpr ? ((setter: any) => (v: any /** TODO #9100 */) => setter(this.scope, v))(setter) : | 
					
						
							|  |  |  |                                ((getter: any) => (v: any /** TODO #9100 */) => getter(this.scope, {$event: v}))(getter) | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |           }); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           throw new Error(`Missing emitter '${output.prop}' on component '${this.info.selector}'!`); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   registerCleanup() { | 
					
						
							| 
									
										
										
										
											2016-04-16 13:46:53 +03:00
										 |  |  |     this.element.bind('$destroy', () => { | 
					
						
							|  |  |  |       this.componentScope.$destroy(); | 
					
						
							| 
									
										
										
										
											2016-04-13 17:05:17 -07:00
										 |  |  |       this.componentRef.destroy(); | 
					
						
							| 
									
										
										
										
											2016-04-16 13:46:53 +03:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Ng1Change implements SimpleChange { | 
					
						
							|  |  |  |   constructor(public previousValue: any, public currentValue: any) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   isFirstChange(): boolean { return this.previousValue === this.currentValue; } | 
					
						
							|  |  |  | } |