How to make AngularDart request templates from an absolute URL?


When AngularDart requests an HTML template, it requests a URL relative to the broswer’s current URL. E.g. if the user is currently at /, then AngularDart might request a template URL like /packages/myapp/components/mycomponent.html. But if the browser location is /foo or /foo/bar, that same exact template would be requested from /foo/myapp/components/mycomponent.html or /foo/bar/myapp/components/mycomponent.html, respectively.

This is obviously undesirable behavior. The URLs /foo and /foo/bar only exist in the AngularDart router (I’m using pushState routing). The server doesn’t know anything about them! Even if the server did have identically named URLs, it won’t have the packages directory symlinked or aliased under all of them.

I tried absolute URLs when declaring the component…

/// The top navigation bar.
    selector: 'nav',
    templateUrl: '/static/dart/web/packages/myapp/component/nav.html',
    useShadowDom: false

…but pub build complains.

[Warning from _Serial on myapp|web/main.dart with input myapp|lib/component/nav.dart]:
line 6, column 1 of package:myapp/component/nav.dart: Cannot cache non-package absolute URIs. /static/dart/web/packages/myapp/component/nav.html

The blessed way to declare a templateUrl is to make it a relative URL that starts with packages/.

/// The top navigation bar.
    selector: 'nav',
    templateUrl: 'packages/myapp/component/nav.html',
    useShadowDom: false

So it seems like I’m forced to use relative URLs for templates even though the browser’s location is completely divorced from where things are stored on the server.

So how should I tell AngularDart to request these templates from an absolute URL, rather than constructing a URL relative to the browser’s current location?


Angular 1

I don’t have an ideal solution, but here’s something that helps. I declared a <base href='…'> element at the document level so that all relative links will be resolved relative to that base URL, not the browser’s location (which, as mentioned in the question, is divorced from the actual server resource being accessed).

<!DOCTYPE html>
<html ng-app>
    <title>My App</title>
    <base href="/static/dart/">

This will cause AngularDart template URLs to resolve to absolute URLs like /static/dart/packages/myapp/components/mycomponent.html, regardless of the browser’s location. This set up works for my development environment, but the base href needs to be changed for production to point to pub build artifacts. I’ve omitted that part from my answer since it’s unique to my server-side software and has nothing to do with Dart or Angular.

The downside to this approach is that you won’t be able to use relative URLs for anything else: they will all be resolved with respect to the <base> element.

Angular 2

Sigh… 18 months later and the brand-new-shiny Angular 2 has the same exact problem, except that the solution for Angular 1 doesn’t work in Angular 2.

You must inject a custom UrlResolver, e.g.

import 'package:angular2/platform/browser.dart' show bootstrap;
import 'package:angular2/src/compiler/url_resolver.dart' show UrlResolver;
import 'package:angular2/src/core/di/provider.dart' show provide;
import 'package:myapp/component/app.dart' show AppComponent;

void main() {
    bootstrap(AppComponent, [
        provide(UrlResolver, useFactory:() => new UrlResolver('/static/dart/web/packages'))

Answered By – Mark E. Haase

Answer Checked By – Timothy Miller (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *