1

I've been working through the Angular 2 tutorial (in TypeScript) when I got stuck on this part. They now want to separate templates into separate files. That's fine and dandy, but I've got a quirky setup: I'm serving up the files with ASP.NET MVC, and it's refusing to serve up the file from the Views folder. Fair enough: I anticipate needing to serve up Razor (.cshtml) files, so I'm happy to try and hack this out instead of just whitelisting .html.

I've worked with Angular 1 before, and in this situation I used a decorator to modify the $templateRequest service to modify the template URLs into something MVC will accept, and then I set up MVC to serve up the corresponding files. Quite clever work if I do say so myself. So I just need to replicate this in Angular 2, right? That should be easy.

Wrong. So wrong. After some guesswork Googling I found UrlResolver which, after some client-side debugging I confirmed, is the class I want to extend. The documentation even says:

This class can be overridden by the application developer to create custom behavior.

Yes! This is exactly what I want to do. Unfortunately no examples of how to override it have been supplied. I've found this DemoUrlResolver and this MyUrlResolver, but I can't figure out how or if either of them works. I've tried the multiple approaches to supplying my custom provider (see this answer) including the bootstrap and providers (on the module and the app component) approaches all to no avail.

How do I override UrlResolver?

I assume it doesn't matter, but at the moment my extension does nothing but defer to the base class:

class MvcUrlResolver extends UrlResolver {
    resolve(baseUrl: string, url: string): string {
        return super.resolve(baseUrl, url);
    }
}
Community
  • 1
  • 1
ricksmt
  • 888
  • 2
  • 13
  • 34

1 Answers1

1

Interesting question. Since it is part of compiler it makes sense that it would not be instantiated along with other application components, and after some research and analyzing angular's code I found the solution. You need to provide it directly in the call to platformBrowserDynamic(). In this case it will be merged into default compiler options and will be used by injector that instantiates compiler.

import { COMPILER_OPTIONS } from '@angular/core';

class MvcUrlResolver extends UrlResolver {
    resolve(baseUrl: string, url: string): string {
        let result = super.resolve(baseUrl, url);
        console.log('resolving urls: baseUrl = ' + baseUrl + '; url = ' + url + '; result = ' + result);
        return result;
    }
}

platformBrowserDynamic([{
    provide: COMPILER_OPTIONS,
    useValue: {providers: [{provide: UrlResolver, useClass: MvcUrlResolver}]},
    multi: true
}]).bootstrapModule(AppModule);
Alexander Leonov
  • 4,694
  • 1
  • 17
  • 25
  • I assume you included `import { COMPILER_OPTIONS } from '@angular/core';`. You are fabulous. I feel I've come with a lot of difficult questions lately, and this has been the first good answer in a while. – ricksmt Feb 10 '17 at 01:36
  • @ricksmt, correct, it's from @angular/core. I've updated my answer. – Alexander Leonov Feb 10 '17 at 01:51