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

user7747472 picture user7747472 · May 6, 2019 · Viewed 9.8k times · Source

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:

Answer

lolcatzftw picture lolcatzftw · May 9, 2019

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)
        }
    } 
}