Angular 7 : How can i get the complete URL of the current page

12,721

The universal server side isn't aware of the window.location.

The express server on the other hand knows the url from the request that was being sent to the server side.

So we need to inject the request url from express into angular..

server.ts

let template = readFileSync(join(__dirname, '..', 'dist', 'index.html')).toString();

app.engine('html', (_, options, callback) => {
    renderModuleFactory(AppServerModuleNgFactory, {
        document: template,
        url: options.req.url,
        extraProviders: [
            { provide: 'requestUrl', useFactory: () => options.req.url, deps: [] },    // 1. set up the provider for the url
            provideModuleMap(LAZY_MODULE_MAP)
        ]
    }).then(html => {
        callback(null, html);
    });
});

..in order to retrieve it where we need it..

url-logger.ts

class UrlLogger {
    constructor(
        private window: Location,
        private injector: Injector,                         // 2. we need the injector to ..
        @Inject(PLATFORM_ID) private platformId: string,
    ) { }

    public log() {
        if (isPlatformServer(this.platformId)) {
            const requestUrl = this.injector.get('requestUrl');    // 3. ..retrieve the injected url
            console.log('server greets you via ' + requestUrl)
        } else {
            console.log('browser says hello from ' + window.location.href)
        }
    } 
}
Share:
12,721
user7747472
Author by

user7747472

Updated on June 07, 2022

Comments

  • user7747472
    user7747472 almost 2 years

    How can I get the complete current URL in angular 7 without using window.location.href?

    For example, let's say my current URL is http://localhost:8080/p/drinks?q=cold&price=200

    How can I get the complete URL rather than only /p/drinks?q=cold&price=200?

    I have tried with this.router.url this gives only /p/drinks?q=cold&price=200 not with the complete hostname.

    The reason that I do not want to use window.location.href is that it causes an issue with rendering in ng-toolkit/universal

    I tried to follow this solution which seems to be a same problem as me and also updated

    How to get domain name for service in Angular2

    And here is my code

    windowProvider.js

    import { InjectionToken, FactoryProvider } from '@angular/core';
    
    export const WINDOW = new InjectionToken<Window>('window');
    
    const windowProvider: FactoryProvider = {
      provide: WINDOW,
      useFactory: () => window
    };
    
    export const WINDOW_PROVIDERS = [
      windowProvider
    ];
    

    In app.module.ts

    @NgModule({
        .......
        providers:[
        .......
        windowProvider
       ]
    })
    

    And in my required page :

    import {WINDOW as WindowFactory} from '../../factory/windowProvider';
    ......
     constructor(private router: Router, private helper: Helpers,
                 @Inject(WindowFactory) private windowFactory: any,
                ) {
    console.warn('HELLO I M WINDOW FACTORY', this.windowFactory.location.hostname);
    }
    

    Buy this gives error at the time of compilation

    ERROR in ./src/app/factory/windowProvider.js 5:20 Module parse failed: Unexpected token (5:20) You may need an appropriate loader to handle this file type. | export const WINDOW = new InjectionToken('window'); |

    const windowProvider: FactoryProvider = { | provide: WINDOW, | useFactory: () => window ℹ 「wdm」: Failed to compile.

    Can anyone please tell how I can get this resolved. Thanks,

    More links that I followed:

  • user7747472
    user7747472 about 5 years
    template is a constant or like what it is. If i import it from angular core then it throws error
  • lolcatzftw
    lolcatzftw about 5 years
    template is the complete path to your template index.html: "The renderModuleFactory() function takes as inputs a template HTML page (usually index.html), an Angular module containing components, and a route that determines which components to display" citation from angular docs. I also edited the answer accordingly.