Camilo Terevinto Camilo Terevinto - 3 years ago 280
TypeScript Question

How to inject data in server-side from createServerRender?

I've been reading some tutorials but none so far are deep enough (or new enough) to show how to actually pass the data to a component. This is the farthest I could get:

In

boot.server.ts
:

export default createServerRenderer(params => {
const providers = [
// default providers here
{ provide: 'MYDATA', useValue: params.data.myData }
];
return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {
// default implementation
});


In a component:

import { Component, Inject } from '@angular/core';
@Component({
selector: 'nav-menu',
templateUrl: './navmenu.component.html',
styleUrls: ['./navmenu.component.css']
})
export class NavMenuComponent
{
constructor(@Inject("MYDATA") myData: string) { }
}


But this fails with
No provider for 'MYDATA'!


I was able to get the data into the
window
but this obviously doesn't work at
server-side
.

I am not sure whether I need to add
MYDATA
as a provider in
app.module.server.ts
and if so how that's done.

Answer Source

If you are reading this from the future (~2018) then use BrowserTransferStateModule and ServerTransferStateModule instead.


Looks like you have this error on the client side. You probably forgot to specify provider for the MYDATA for the client side. I normally do this in app.module.browser.ts (previously named app.module.client.ts) For example like this:

@NgModule({
    bootstrap: [AppComponent],
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        AppSharedModule
    ],
    providers: [
        { provide: 'MYDATA', useFactory: getMyData }
    ]
})
export class AppModule
{
}

/**
 * reads state from the dom generated on the server side
 */
export function getMyData()
{
    const appState = document.querySelector("app-state");
    if (appState)
    {
        return JSON.parse(appState.textContent!);
    }
    return null;
}

To save your server side state you can use the following technique:

import { Component, PLATFORM_ID, Inject } from '@angular/core';
import { isPlatformServer } from '@angular/common';

@Component({
    selector: 'app-state',
    template: '{{state|json}}'
})
/** state component*/
export class StateComponent 
{
    state: any;

    /** state ctor */
    constructor(@Inject(PLATFORM_ID) platformId: any)
    {
        if (isPlatformServer(platformId))
        {
            this.state = {
                prop: "some state determined on the server side"
            }
        }
    }
}

And in your app.component.html you can put state component like this or add condition to skip it on the client side:

<app-state></app-state>

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download