| 
									
										
										
										
											2016-06-23 09:47:54 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | import {Directive, DoCheck, ElementRef, EventEmitter, Inject, OnChanges, OnInit, SimpleChange, SimpleChanges, Type} from '@angular/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-26 20:17:46 -07:00
										 |  |  | import * as angular from './angular_js'; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | import {NG1_COMPILE, NG1_CONTROLLER, NG1_HTTP_BACKEND, NG1_SCOPE, NG1_TEMPLATE_CACHE} from './constants'; | 
					
						
							|  |  |  | import {controllerKey} from './util'; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | const CAMEL_CASE = /([A-Z])/g; | 
					
						
							|  |  |  | const INITIAL_VALUE = { | 
					
						
							|  |  |  |   __UNINITIALIZED__: true | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  | const NOT_SUPPORTED: any = 'NOT_SUPPORTED'; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-12 21:32:41 -07:00
										 |  |  | export class UpgradeNg1ComponentAdapterBuilder { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   type: Type; | 
					
						
							|  |  |  |   inputs: string[] = []; | 
					
						
							|  |  |  |   inputsRename: string[] = []; | 
					
						
							|  |  |  |   outputs: string[] = []; | 
					
						
							|  |  |  |   outputsRename: string[] = []; | 
					
						
							|  |  |  |   propertyOutputs: string[] = []; | 
					
						
							|  |  |  |   checkProperties: string[] = []; | 
					
						
							|  |  |  |   propertyMap: {[name: string]: string} = {}; | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |   linkFn: angular.ILinkFn = null; | 
					
						
							|  |  |  |   directive: angular.IDirective = null; | 
					
						
							|  |  |  |   $controller: angular.IControllerService = null; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   constructor(public name: string) { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |     var selector = name.replace( | 
					
						
							|  |  |  |         CAMEL_CASE, (all: any /** TODO #9100 */, next: string) => '-' + next.toLowerCase()); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     var self = this; | 
					
						
							|  |  |  |     this.type = | 
					
						
							|  |  |  |         Directive({selector: selector, inputs: this.inputsRename, outputs: this.outputsRename}) | 
					
						
							|  |  |  |             .Class({ | 
					
						
							|  |  |  |               constructor: [ | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |                 new Inject(NG1_SCOPE), ElementRef, | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |                 function(scope: angular.IScope, elementRef: ElementRef) { | 
					
						
							|  |  |  |                   return new UpgradeNg1ComponentAdapter( | 
					
						
							|  |  |  |                       self.linkFn, scope, self.directive, elementRef, self.$controller, self.inputs, | 
					
						
							|  |  |  |                       self.outputs, self.propertyOutputs, self.checkProperties, self.propertyMap); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |                 } | 
					
						
							|  |  |  |               ], | 
					
						
							| 
									
										
										
										
											2016-03-14 07:51:04 +01:00
										 |  |  |               ngOnInit: function() { /* needs to be here for ng2 to properly detect it */ }, | 
					
						
							| 
									
										
											  
											
												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
										 |  |  |               ngOnChanges: function() { /* needs to be here for ng2 to properly detect it */ }, | 
					
						
							|  |  |  |               ngDoCheck: function() { /* needs to be here for ng2 to properly detect it */ } | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |             }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-26 20:17:46 -07:00
										 |  |  |   extractDirective(injector: angular.IInjectorService): angular.IDirective { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     var directives: angular.IDirective[] = injector.get(this.name + 'Directive'); | 
					
						
							|  |  |  |     if (directives.length > 1) { | 
					
						
							|  |  |  |       throw new Error('Only support single directive definition for: ' + this.name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     var directive = directives[0]; | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |     if (directive.replace) this.notSupported('replace'); | 
					
						
							|  |  |  |     if (directive.terminal) this.notSupported('terminal'); | 
					
						
							|  |  |  |     var link = directive.link; | 
					
						
							|  |  |  |     if (typeof link == 'object') { | 
					
						
							|  |  |  |       if ((<angular.IDirectivePrePost>link).post) this.notSupported('link.post'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return directive; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private notSupported(feature: string) { | 
					
						
							|  |  |  |     throw new Error(`Upgraded directive '${this.name}' does not support '${feature}'.`); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   extractBindings() { | 
					
						
							| 
									
										
										
										
											2015-11-13 18:55:40 +01:00
										 |  |  |     var btcIsObject = typeof this.directive.bindToController === 'object'; | 
					
						
							|  |  |  |     if (btcIsObject && Object.keys(this.directive.scope).length) { | 
					
						
							|  |  |  |       throw new Error( | 
					
						
							|  |  |  |           `Binding definitions on scope and controller at the same time are not supported.`); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var context = (btcIsObject) ? this.directive.bindToController : this.directive.scope; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (typeof context == 'object') { | 
					
						
							|  |  |  |       for (var name in context) { | 
					
						
							|  |  |  |         if ((<any>context).hasOwnProperty(name)) { | 
					
						
							|  |  |  |           var localName = context[name]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |           var type = localName.charAt(0); | 
					
						
							|  |  |  |           localName = localName.substr(1) || name; | 
					
						
							|  |  |  |           var outputName = 'output_' + name; | 
					
						
							|  |  |  |           var outputNameRename = outputName + ': ' + name; | 
					
						
							| 
									
										
										
										
											2015-10-10 19:56:22 -07:00
										 |  |  |           var outputNameRenameChange = outputName + ': ' + name + 'Change'; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |           var inputName = 'input_' + name; | 
					
						
							|  |  |  |           var inputNameRename = inputName + ': ' + name; | 
					
						
							|  |  |  |           switch (type) { | 
					
						
							|  |  |  |             case '=': | 
					
						
							|  |  |  |               this.propertyOutputs.push(outputName); | 
					
						
							|  |  |  |               this.checkProperties.push(localName); | 
					
						
							|  |  |  |               this.outputs.push(outputName); | 
					
						
							| 
									
										
										
										
											2015-10-10 19:56:22 -07:00
										 |  |  |               this.outputsRename.push(outputNameRenameChange); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |               this.propertyMap[outputName] = localName; | 
					
						
							| 
									
										
										
										
											2016-06-22 15:57:24 -07:00
										 |  |  |               this.inputs.push(inputName); | 
					
						
							|  |  |  |               this.inputsRename.push(inputNameRename); | 
					
						
							|  |  |  |               this.propertyMap[inputName] = localName; | 
					
						
							|  |  |  |               break; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |             case '@': | 
					
						
							| 
									
										
										
										
											2016-03-14 07:51:04 +01:00
										 |  |  |             // handle the '<' binding of angular 1.5 components
 | 
					
						
							|  |  |  |             case '<': | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |               this.inputs.push(inputName); | 
					
						
							|  |  |  |               this.inputsRename.push(inputNameRename); | 
					
						
							|  |  |  |               this.propertyMap[inputName] = localName; | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             case '&': | 
					
						
							|  |  |  |               this.outputs.push(outputName); | 
					
						
							|  |  |  |               this.outputsRename.push(outputNameRename); | 
					
						
							|  |  |  |               this.propertyMap[outputName] = localName; | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             default: | 
					
						
							| 
									
										
										
										
											2015-11-13 18:55:40 +01:00
										 |  |  |               var json = JSON.stringify(context); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |               throw new Error( | 
					
						
							|  |  |  |                   `Unexpected mapping '${type}' in '${json}' in '${this.name}' directive.`); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   compileTemplate( | 
					
						
							|  |  |  |       compile: angular.ICompileService, templateCache: angular.ITemplateCacheService, | 
					
						
							|  |  |  |       httpBackend: angular.IHttpBackendService): Promise<any> { | 
					
						
							| 
									
										
										
										
											2015-12-10 13:23:47 +01:00
										 |  |  |     if (this.directive.template !== undefined) { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |       this.linkFn = compileHtml( | 
					
						
							|  |  |  |           typeof this.directive.template === 'function' ? this.directive.template() : | 
					
						
							|  |  |  |                                                           this.directive.template); | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |     } else if (this.directive.templateUrl) { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |       var url = typeof this.directive.templateUrl === 'function' ? this.directive.templateUrl() : | 
					
						
							|  |  |  |                                                                    this.directive.templateUrl; | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |       var html = templateCache.get(url); | 
					
						
							|  |  |  |       if (html !== undefined) { | 
					
						
							|  |  |  |         this.linkFn = compileHtml(html); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         return new Promise((resolve, err) => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           httpBackend( | 
					
						
							|  |  |  |               'GET', url, null, | 
					
						
							|  |  |  |               (status: any /** TODO #9100 */, response: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |                 if (status == 200) { | 
					
						
							|  |  |  |                   resolve(this.linkFn = compileHtml(templateCache.put(url, response))); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                   err(`GET ${url} returned ${status}: ${response}`); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               }); | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       throw new Error(`Directive '${this.name}' is not a component, it is missing template.`); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return null; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |     function compileHtml(html: any /** TODO #9100 */): angular.ILinkFn { | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |       var div = document.createElement('div'); | 
					
						
							|  |  |  |       div.innerHTML = html; | 
					
						
							|  |  |  |       return compile(div.childNodes); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   static resolve( | 
					
						
							|  |  |  |       exportedComponents: {[name: string]: UpgradeNg1ComponentAdapterBuilder}, | 
					
						
							|  |  |  |       injector: angular.IInjectorService): Promise<any> { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |     var promises: any[] /** TODO #9100 */ = []; | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |     var compile: angular.ICompileService = injector.get(NG1_COMPILE); | 
					
						
							|  |  |  |     var templateCache: angular.ITemplateCacheService = injector.get(NG1_TEMPLATE_CACHE); | 
					
						
							|  |  |  |     var httpBackend: angular.IHttpBackendService = injector.get(NG1_HTTP_BACKEND); | 
					
						
							|  |  |  |     var $controller: angular.IControllerService = injector.get(NG1_CONTROLLER); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     for (var name in exportedComponents) { | 
					
						
							| 
									
										
										
										
											2015-10-09 21:19:00 -07:00
										 |  |  |       if ((<any>exportedComponents).hasOwnProperty(name)) { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |         var exportedComponent = exportedComponents[name]; | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |         exportedComponent.directive = exportedComponent.extractDirective(injector); | 
					
						
							|  |  |  |         exportedComponent.$controller = $controller; | 
					
						
							|  |  |  |         exportedComponent.extractBindings(); | 
					
						
							|  |  |  |         var promise = exportedComponent.compileTemplate(compile, templateCache, httpBackend); | 
					
						
							| 
									
										
										
										
											2015-10-26 20:17:46 -07:00
										 |  |  |         if (promise) promises.push(promise); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |     return Promise.all(promises); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | class UpgradeNg1ComponentAdapter implements OnInit, OnChanges, DoCheck { | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |   destinationObj: any = null; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   checkLastValues: any[] = []; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   componentScope: angular.IScope; | 
					
						
							|  |  |  |   element: Element; | 
					
						
							| 
									
										
										
										
											2016-05-17 14:53:59 -07:00
										 |  |  |   $element: any = null; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   constructor( | 
					
						
							|  |  |  |       private linkFn: angular.ILinkFn, scope: angular.IScope, private directive: angular.IDirective, | 
					
						
							|  |  |  |       elementRef: ElementRef, private $controller: angular.IControllerService, | 
					
						
							|  |  |  |       private inputs: string[], private outputs: string[], private propOuts: string[], | 
					
						
							|  |  |  |       private checkProperties: string[], private propertyMap: {[key: string]: string}) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     this.element = elementRef.nativeElement; | 
					
						
							|  |  |  |     this.componentScope = scope.$new(!!directive.scope); | 
					
						
							| 
									
										
										
										
											2016-05-17 14:53:59 -07:00
										 |  |  |     this.$element = angular.element(this.element); | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |     var controllerType = directive.controller; | 
					
						
							| 
									
										
										
										
											2016-05-17 14:53:59 -07:00
										 |  |  |     if (directive.bindToController && controllerType) { | 
					
						
							|  |  |  |       this.destinationObj = this.buildController(controllerType); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       this.destinationObj = this.componentScope; | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (var i = 0; i < inputs.length; i++) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |       (this as any /** TODO #9100 */)[inputs[i]] = null; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |     for (var j = 0; j < outputs.length; j++) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |       var emitter = (this as any /** TODO #9100 */)[outputs[j]] = new EventEmitter(); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |       this.setComponentProperty( | 
					
						
							|  |  |  |           outputs[j], ((emitter: any /** TODO #9100 */) => (value: any /** TODO #9100 */) => | 
					
						
							|  |  |  |                            emitter.emit(value))(emitter)); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |     for (var k = 0; k < propOuts.length; k++) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |       (this as any /** TODO #9100 */)[propOuts[k]] = new EventEmitter(); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       this.checkLastValues.push(INITIAL_VALUE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-14 07:51:04 +01:00
										 |  |  |   ngOnInit() { | 
					
						
							| 
									
										
										
										
											2016-05-17 14:53:59 -07:00
										 |  |  |     if (!this.directive.bindToController && this.directive.controller) { | 
					
						
							| 
									
										
										
										
											2016-05-26 13:33:53 -07:00
										 |  |  |       this.buildController(this.directive.controller); | 
					
						
							| 
									
										
										
										
											2016-05-17 14:53:59 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |     var link = this.directive.link; | 
					
						
							|  |  |  |     if (typeof link == 'object') link = (<angular.IDirectivePrePost>link).pre; | 
					
						
							|  |  |  |     if (link) { | 
					
						
							|  |  |  |       var attrs: angular.IAttributes = NOT_SUPPORTED; | 
					
						
							|  |  |  |       var transcludeFn: angular.ITranscludeFunction = NOT_SUPPORTED; | 
					
						
							|  |  |  |       var linkController = this.resolveRequired(this.$element, this.directive.require); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |       (<angular.IDirectiveLinkFn>this.directive.link)( | 
					
						
							|  |  |  |           this.componentScope, this.$element, attrs, linkController, transcludeFn); | 
					
						
							| 
									
										
										
										
											2016-05-17 14:53:59 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     var childNodes: Node[] = []; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |     var childNode: any /** TODO #9100 */; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     while (childNode = this.element.firstChild) { | 
					
						
							|  |  |  |       this.element.removeChild(childNode); | 
					
						
							|  |  |  |       childNodes.push(childNode); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     this.linkFn(this.componentScope, (clonedElement: Node[], scope: angular.IScope) => { | 
					
						
							|  |  |  |       for (var i = 0, ii = clonedElement.length; i < ii; i++) { | 
					
						
							|  |  |  |         this.element.appendChild(clonedElement[i]); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |     }, { | 
					
						
							|  |  |  |       parentBoundTranscludeFn: (scope: any /** TODO #9100 */, | 
					
						
							|  |  |  |                                 cloneAttach: any /** TODO #9100 */) => { cloneAttach(childNodes); } | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-03-14 07:51:04 +01:00
										 |  |  |     if (this.destinationObj.$onInit) { | 
					
						
							|  |  |  |       this.destinationObj.$onInit(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-09 15:45:04 -07:00
										 |  |  |   ngOnChanges(changes: SimpleChanges) { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     for (var name in changes) { | 
					
						
							| 
									
										
										
										
											2015-10-26 20:17:46 -07:00
										 |  |  |       if ((<Object>changes).hasOwnProperty(name)) { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |         var change: SimpleChange = changes[name]; | 
					
						
							|  |  |  |         this.setComponentProperty(name, change.currentValue); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												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
										 |  |  |   ngDoCheck(): number { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     var count = 0; | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |     var destinationObj = this.destinationObj; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     var lastValues = this.checkLastValues; | 
					
						
							|  |  |  |     var checkProperties = this.checkProperties; | 
					
						
							|  |  |  |     for (var i = 0; i < checkProperties.length; i++) { | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |       var value = destinationObj[checkProperties[i]]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       var last = lastValues[i]; | 
					
						
							|  |  |  |       if (value !== last) { | 
					
						
							|  |  |  |         if (typeof value == 'number' && isNaN(value) && typeof last == 'number' && isNaN(last)) { | 
					
						
							|  |  |  |           // ignore because NaN != NaN
 | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |           var eventEmitter: EventEmitter<any> = (this as any /** TODO #9100 */)[this.propOuts[i]]; | 
					
						
							| 
									
										
										
										
											2015-11-15 23:58:59 -08:00
										 |  |  |           eventEmitter.emit(lastValues[i] = value); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return count; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   setComponentProperty(name: string, value: any) { | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |     this.destinationObj[this.propertyMap[name]] = value; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |   private buildController(controllerType: any /** TODO #9100 */) { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |     var locals = {$scope: this.componentScope, $element: this.$element}; | 
					
						
							|  |  |  |     var controller: any = | 
					
						
							|  |  |  |         this.$controller(controllerType, locals, null, this.directive.controllerAs); | 
					
						
							| 
									
										
										
										
											2016-05-17 14:53:59 -07:00
										 |  |  |     this.$element.data(controllerKey(this.directive.name), controller); | 
					
						
							|  |  |  |     return controller; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   private resolveRequired($element: angular.IAugmentedJQuery, require: string|string[]): any { | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |     if (!require) { | 
					
						
							|  |  |  |       return undefined; | 
					
						
							|  |  |  |     } else if (typeof require == 'string') { | 
					
						
							|  |  |  |       var name: string = <string>require; | 
					
						
							|  |  |  |       var isOptional = false; | 
					
						
							|  |  |  |       var startParent = false; | 
					
						
							|  |  |  |       var searchParents = false; | 
					
						
							|  |  |  |       var ch: string; | 
					
						
							|  |  |  |       if (name.charAt(0) == '?') { | 
					
						
							|  |  |  |         isOptional = true; | 
					
						
							|  |  |  |         name = name.substr(1); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (name.charAt(0) == '^') { | 
					
						
							|  |  |  |         searchParents = true; | 
					
						
							|  |  |  |         name = name.substr(1); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (name.charAt(0) == '^') { | 
					
						
							|  |  |  |         startParent = true; | 
					
						
							|  |  |  |         name = name.substr(1); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var key = controllerKey(name); | 
					
						
							|  |  |  |       if (startParent) $element = $element.parent(); | 
					
						
							|  |  |  |       var dep = searchParents ? $element.inheritedData(key) : $element.data(key); | 
					
						
							|  |  |  |       if (!dep && !isOptional) { | 
					
						
							|  |  |  |         throw new Error(`Can not locate '${require}' in '${this.directive.name}'.`); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return dep; | 
					
						
							|  |  |  |     } else if (require instanceof Array) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:45:15 -07:00
										 |  |  |       var deps: any[] /** TODO #9100 */ = []; | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |       for (var i = 0; i < require.length; i++) { | 
					
						
							|  |  |  |         deps.push(this.resolveRequired($element, require[i])); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return deps; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     throw new Error( | 
					
						
							|  |  |  |         `Directive '${this.directive.name}' require syntax unrecognized: ${this.directive.require}`); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | } |