mehaase mehaase - 2 months ago 24
Dart Question

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
. But if the browser location is
, that same exact template would be requested from
, respectively.

This is obviously undesirable behavior. The URLs
only exist in the AngularDart router (I'm using
routing). The server doesn't know anything about them! Even if the server did have identically named URLs, it won't have the
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

pub build

[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
is to make it a relative URL that starts with

/// 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'))