@@ -7,10 +7,12 @@ import {
77 ApplicationRef ,
88 AppViewManager ,
99 Compiler ,
10+ Inject ,
1011 Injector ,
1112 NgZone ,
1213 PlatformRef ,
1314 ProtoViewRef ,
15+ Provider ,
1416 Type
1517} from 'angular2/angular2' ;
1618import { applicationDomBindings } from 'angular2/src/core/application_common' ;
@@ -113,6 +115,8 @@ export class UpgradeAdapter {
113115 private upgradedComponents : Type [ ] = [ ] ;
114116 /* @internal */
115117 private downgradedComponents : { [ name : string ] : UpgradeNg1ComponentAdapterBuilder } = { } ;
118+ /* @internal */
119+ private providers : Array < Type | Provider | any [ ] > = [ ] ;
116120
117121 /**
118122 * Allows Angular v2 Component to be used from AngularJS v1.
@@ -298,7 +302,8 @@ export class UpgradeAdapter {
298302 applicationDomBindings ( ) ,
299303 compilerProviders ( ) ,
300304 provide ( NG1_INJECTOR , { useFactory : ( ) => ng1Injector } ) ,
301- provide ( NG1_COMPILE , { useFactory : ( ) => ng1Injector . get ( NG1_COMPILE ) } )
305+ provide ( NG1_COMPILE , { useFactory : ( ) => ng1Injector . get ( NG1_COMPILE ) } ) ,
306+ this . providers
302307 ] ) ;
303308 var injector : Injector = applicationRef . injector ;
304309 var ngZone : NgZone = injector . get ( NgZone ) ;
@@ -349,16 +354,125 @@ export class UpgradeAdapter {
349354 Promise . all ( [ this . compileNg2Components ( compiler , protoViewRefMap ) , ng1compilePromise ] )
350355 . then ( ( ) => {
351356 ngZone . run ( ( ) => {
352- rootScopePrototype . $apply = original$applyFn ; // restore original $apply
353- while ( delayApplyExps . length ) {
354- rootScope . $apply ( delayApplyExps . shift ( ) ) ;
357+ if ( rootScopePrototype ) {
358+ rootScopePrototype . $apply = original$applyFn ; // restore original $apply
359+ while ( delayApplyExps . length ) {
360+ rootScope . $apply ( delayApplyExps . shift ( ) ) ;
361+ }
362+ ( < any > upgrade ) . _bootstrapDone ( applicationRef , ng1Injector ) ;
363+ rootScopePrototype = null ;
355364 }
356- ( < any > upgrade ) . _bootstrapDone ( applicationRef , ng1Injector ) ;
357365 } ) ;
358366 } , onError ) ;
359367 return upgrade ;
360368 }
361369
370+ /**
371+ * Adds a provider to the top level environment of a hybrid AngularJS v1 / Angular v2 application.
372+ *
373+ * In hybrid AngularJS v1 / Angular v2 application, there is no one root Angular v2 component,
374+ * for this reason we provide an application global way of registering providers which is
375+ * consistent with single global injection in AngularJS v1.
376+ *
377+ * ## Example
378+ *
379+ * ```
380+ * class Greeter {
381+ * greet(name) {
382+ * alert('Hello ' + name + '!');
383+ * }
384+ * }
385+ *
386+ * @Component ({
387+ * selector: 'app',
388+ * template: ''
389+ * })
390+ * class App {
391+ * constructor(greeter: Greeter) {
392+ * this.greeter('World');
393+ * }
394+ * }
395+ *
396+ * var adapter = new UpgradeAdapter();
397+ * adapter.addProvider(Greeter);
398+ *
399+ * var module = angular.module('myExample', []);
400+ * module.directive('app', adapter.downgradeNg2Component(App));
401+ *
402+ * document.body.innerHTML = '<app></app>'
403+ * adapter.bootstrap(document.body, ['myExample']);
404+ *```
405+ */
406+ public addProvider ( provider : Type | Provider | any [ ] ) : void { this . providers . push ( provider ) ; }
407+
408+ /**
409+ * Allows AngularJS v1 service to be accessible from Angular v2.
410+ *
411+ *
412+ * ## Example
413+ *
414+ * ```
415+ * class Login { ... }
416+ * class Server { ... }
417+ *
418+ * @Injectable ()
419+ * class Example {
420+ * constructor(@Inject ('server') server, login: Login) {
421+ * ...
422+ * }
423+ * }
424+ *
425+ * var module = angular.module('myExample', []);
426+ * module.service('server', Server);
427+ * module.service('login', Login);
428+ *
429+ * var adapter = new UpgradeAdapter();
430+ * adapter.upgradeNg1Provider('server');
431+ * adapter.upgradeNg1Provider('login', {asToken: Login});
432+ * adapter.addProvider(Example);
433+ *
434+ * adapter.bootstrap(document.body, ['myExample']).ready((ref) => {
435+ * var example: Example = ref.ng2Injector.get(Example);
436+ * });
437+ *
438+ * ```
439+ */
440+ public upgradeNg1Provider ( name : string , options ?: { asToken : any } ) {
441+ var token = options && options . asToken || name ;
442+ this . providers . push ( provide ( token , {
443+ useFactory : ( ng1Injector : angular . auto . IInjectorService ) => ng1Injector . get ( name ) ,
444+ deps : [ NG1_INJECTOR ]
445+ } ) ) ;
446+ }
447+
448+ /**
449+ * Allows Angular v2 service to be accessible from AngularJS v1.
450+ *
451+ *
452+ * ## Example
453+ *
454+ * ```
455+ * class Example {
456+ * }
457+ *
458+ * var adapter = new UpgradeAdapter();
459+ * adapter.addProvider(Example);
460+ *
461+ * var module = angular.module('myExample', []);
462+ * module.factory('example', adapter.downgradeNg2Provider(Example));
463+ *
464+ * adapter.bootstrap(document.body, ['myExample']).ready((ref) => {
465+ * var example: Example = ref.ng1Injector.get('example');
466+ * });
467+ *
468+ * ```
469+ */
470+ public downgradeNg2Provider ( token : any ) : Function {
471+ var factory = function ( injector : Injector ) { return injector . get ( token ) ; } ;
472+ factory . $inject = [ NG2_INJECTOR ] ;
473+ return factory ;
474+ }
475+
362476 /* @internal */
363477 private compileNg2Components ( compiler : Compiler ,
364478 protoViewRefMap : ProtoViewRefMap ) : Promise < ProtoViewRefMap > {
@@ -417,14 +531,18 @@ export class UpgradeAdapterRef {
417531 /* @internal */
418532 private _readyFn : ( upgradeAdapterRef ?: UpgradeAdapterRef ) => void = null ;
419533
420- public applicationRef : ApplicationRef = null ;
534+ public ng1RootScope : angular . IRootScopeService = null ;
421535 public ng1Injector : angular . auto . IInjectorService = null ;
536+ public ng2ApplicationRef : ApplicationRef = null ;
537+ public ng2Injector : Injector = null ;
422538
423539 /* @internal */
424540 private _bootstrapDone ( applicationRef : ApplicationRef ,
425541 ng1Injector : angular . auto . IInjectorService ) {
426- this . applicationRef = applicationRef ;
542+ this . ng2ApplicationRef = applicationRef ;
543+ this . ng2Injector = applicationRef . injector ;
427544 this . ng1Injector = ng1Injector ;
545+ this . ng1RootScope = ng1Injector . get ( NG1_ROOT_SCOPE ) ;
428546 this . _readyFn && this . _readyFn ( this ) ;
429547 }
430548
@@ -442,6 +560,6 @@ export class UpgradeAdapterRef {
442560 */
443561 public dispose ( ) {
444562 this . ng1Injector . get ( NG1_ROOT_SCOPE ) . $destroy ( ) ;
445- this . applicationRef . dispose ( ) ;
563+ this . ng2ApplicationRef . dispose ( ) ;
446564 }
447565}
0 commit comments