@@ -16,7 +16,7 @@ import {Http, HttpModule, Response, ResponseOptions, XHRBackend} from '@angular/
1616import { MockBackend , MockConnection } from '@angular/http/testing' ;
1717import { BrowserModule , DOCUMENT , Title } from '@angular/platform-browser' ;
1818import { getDOM } from '@angular/platform-browser/src/dom/dom_adapter' ;
19- import { INITIAL_CONFIG , PlatformState , ServerModule , platformDynamicServer , renderModule , renderModuleFactory } from '@angular/platform-server' ;
19+ import { BEFORE_APP_SERIALIZED , INITIAL_CONFIG , PlatformState , ServerModule , platformDynamicServer , renderModule , renderModuleFactory } from '@angular/platform-server' ;
2020import { Subscription } from 'rxjs/Subscription' ;
2121import { filter } from 'rxjs/operator/filter' ;
2222import { first } from 'rxjs/operator/first' ;
@@ -38,6 +38,50 @@ class MyServerApp {
3838class ExampleModule {
3939}
4040
41+ function getTitleRenderHook ( doc : any ) {
42+ return ( ) => {
43+ // Set the title as part of the render hook.
44+ doc . title = 'RenderHook' ;
45+ } ;
46+ }
47+
48+ function exceptionRenderHook ( ) {
49+ throw new Error ( 'error' ) ;
50+ }
51+
52+ function getMetaRenderHook ( doc : any ) {
53+ return ( ) => {
54+ // Add a meta tag before rendering the document.
55+ const metaElement = doc . createElement ( 'meta' ) ;
56+ metaElement . setAttribute ( 'name' , 'description' ) ;
57+ doc . head . appendChild ( metaElement ) ;
58+ } ;
59+ }
60+
61+ @NgModule ( {
62+ bootstrap : [ MyServerApp ] ,
63+ declarations : [ MyServerApp ] ,
64+ imports : [ BrowserModule . withServerTransition ( { appId : 'render-hook' } ) , ServerModule ] ,
65+ providers : [
66+ { provide : BEFORE_APP_SERIALIZED , useFactory : getTitleRenderHook , multi : true , deps : [ DOCUMENT ] } ,
67+ ]
68+ } )
69+ class RenderHookModule {
70+ }
71+
72+ @NgModule ( {
73+ bootstrap : [ MyServerApp ] ,
74+ declarations : [ MyServerApp ] ,
75+ imports : [ BrowserModule . withServerTransition ( { appId : 'render-hook' } ) , ServerModule ] ,
76+ providers : [
77+ { provide : BEFORE_APP_SERIALIZED , useFactory : getTitleRenderHook , multi : true , deps : [ DOCUMENT ] } ,
78+ { provide : BEFORE_APP_SERIALIZED , useValue : exceptionRenderHook , multi : true } ,
79+ { provide : BEFORE_APP_SERIALIZED , useFactory : getMetaRenderHook , multi : true , deps : [ DOCUMENT ] } ,
80+ ]
81+ } )
82+ class MultiRenderHookModule {
83+ }
84+
4185@Component ( { selector : 'app' , template : `Works too!` } )
4286class MyServerApp2 {
4387}
@@ -469,6 +513,28 @@ export function main() {
469513 called = true ;
470514 } ) ;
471515 } ) ) ;
516+
517+ it ( 'should call render hook' , async ( ( ) => {
518+ renderModule ( RenderHookModule , { document : doc } ) . then ( output => {
519+ // title should be added by the render hook.
520+ expect ( output ) . toBe (
521+ '<html><head><title>RenderHook</title></head><body>' +
522+ '<app ng-version="0.0.0-PLACEHOLDER">Works!</app></body></html>' ) ;
523+ called = true ;
524+ } ) ;
525+ } ) ) ;
526+
527+ it ( 'should call mutliple render hooks' , async ( ( ) => {
528+ const consoleSpy = spyOn ( console , 'warn' ) ;
529+ renderModule ( MultiRenderHookModule , { document : doc } ) . then ( output => {
530+ // title should be added by the render hook.
531+ expect ( output ) . toBe (
532+ '<html><head><title>RenderHook</title><meta name="description"></head>' +
533+ '<body><app ng-version="0.0.0-PLACEHOLDER">Works!</app></body></html>' ) ;
534+ expect ( consoleSpy ) . toHaveBeenCalled ( ) ;
535+ called = true ;
536+ } ) ;
537+ } ) ) ;
472538 } ) ;
473539
474540 describe ( 'http' , ( ) => {
0 commit comments