Search code examples
nativescriptangular2-nativescript

Using Router for web and RouterExtensions for mobile in a single component


I am trying to code share in my project between a web and mobile app version.

I have a component that requires programmatic navigation and therefore I need to inject the Angular Router (from '@angular/router') for the web version and NativeScript RouterExtensions (from '@nativescript/angular') for the mobile version. Is there a recommended way to "dynamically" inject a dependency into a component, so that each target that is compiled for gets the correct dependency?


Solution

  • At the first step you should create an injection token

    // src/app/tokens.ts
    import {InjectionToken} from '@angular/core';
    
    export const UNIVERSAL_ROUTER = new InjectionToken<string>('Custom router');
    

    After that in your module which is related to web application (I assume it is app.module.ts) you define it in your providers list

    // src/app/app.module.ts
    ...
    import {Router, RouterModule} from '@angular/router';
    import {UNIVERSAL_ROUTER} from '~/app/tokens';
    
    @NgModule({
        imports: [...],
        declarations: [...],
        providers: [
            {provide: UNIVERSAL_ROUTER, useExisting: Router},
        ],
        bootstrap: [AppComponent],
    })
    export class AppModule {}
    

    Simultaneously you define this token as a RouterExtension in the module which states for mobile application (i.e. app.module.tns.ts):

    // src/app/app.module.tns.ts
    ...
    import {NativeScriptRouterModule, RouterExtensions} from 'nativescript-angular/router';
    import {UNIVERSAL_ROUTER} from '~/app/tokens';
    
    @NgModule({
        imports: [...],
        declarations: [...],
        providers: [
            {provide: UNIVERSAL_ROUTER, useClass: RouterExtensions},
        ],
        bootstrap: [AppComponent],
        schemas: [NO_ERRORS_SCHEMA],
    })
    export class AppModule {}
    
    

    Having this done, you can inject router by means of @Inject decorator like

    constructor(@Inject(UNIVERSAL_ROUTER) private router) {}
    

    and get a platform-specific router wherever you need it.