diff --git a/public/_includes/_util-fns.jade b/public/_includes/_util-fns.jade index 0bb81db082..b3078fb838 100644 --- a/public/_includes/_util-fns.jade +++ b/public/_includes/_util-fns.jade @@ -11,6 +11,10 @@ //- preceded by the article "a". (E.g., will be "annotation" for Dart) - var _decorator = 'decorator'; +//- TS arrays vs. Dart lists +- var _array = 'array'; +- var _an_array = 'an array'; + //- Used to prefix identifiers that are private. In Dart this will be '_'. - var _priv = ''; diff --git a/public/docs/_examples/component-styles/dart/lib/hero.dart b/public/docs/_examples/component-styles/dart/lib/hero.dart new file mode 100755 index 0000000000..cdfecf4d79 --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/hero.dart @@ -0,0 +1,8 @@ +class Hero { + bool active = false; + + final String name; + final List team; + + Hero(this.name, this.team); +} diff --git a/public/docs/_examples/component-styles/dart/lib/hero_app_component.dart b/public/docs/_examples/component-styles/dart/lib/hero_app_component.dart new file mode 100755 index 0000000000..bba326e603 --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/hero_app_component.dart @@ -0,0 +1,21 @@ +import 'package:angular2/core.dart'; +import 'hero.dart'; +import 'hero_app_main_component.dart'; + +// #docregion +@Component( + selector: 'hero-app', + template: ''' +

Tour of Heroes

+ ''', + styles: const ['h1 { font-weight: normal; }'], + directives: const [HeroAppMainComponent]) +class HeroAppComponent { +// #enddocregion + Hero hero = + new Hero('Human Torch', ['Mister Fantastic', 'Invisible Woman', 'Thing']); + + @HostBinding('class') + String get themeClass => 'theme-light'; +// #docregion +} diff --git a/public/docs/_examples/component-styles/dart/lib/hero_app_main_component.dart b/public/docs/_examples/component-styles/dart/lib/hero_app_main_component.dart new file mode 100755 index 0000000000..ddec19537b --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/hero_app_main_component.dart @@ -0,0 +1,22 @@ +import 'package:angular2/core.dart'; + +import 'hero.dart'; +import 'hero_details_component.dart'; +import 'hero_controls_component.dart'; +import 'quest_summary_component.dart'; + +@Component( + selector: 'hero-app-main', + template: ''' + + + + ''', + directives: const [ + HeroDetailsComponent, + HeroControlsComponent, + QuestSummaryComponent + ]) +class HeroAppMainComponent { + @Input() Hero hero; +} diff --git a/public/docs/_examples/component-styles/dart/lib/hero_controls_component.dart b/public/docs/_examples/component-styles/dart/lib/hero_controls_component.dart new file mode 100755 index 0000000000..52ec2e1acb --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/hero_controls_component.dart @@ -0,0 +1,23 @@ +import 'package:angular2/core.dart'; +import 'hero.dart'; + +// #docregion inlinestyles +@Component( + selector: 'hero-controls', + template: ''' + +

Controls

+ ''') +class HeroControlsComponent { + @Input() + Hero hero; + + void activate() { + hero.active = true; + } +} diff --git a/public/docs/_examples/component-styles/dart/lib/hero_details_box.css b/public/docs/_examples/component-styles/dart/lib/hero_details_box.css new file mode 100755 index 0000000000..443c863cb4 --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/hero_details_box.css @@ -0,0 +1,6 @@ +:host { + padding: 10px; +} +h3 { + background-color: yellow; +} diff --git a/public/docs/_examples/component-styles/dart/lib/hero_details_component.css b/public/docs/_examples/component-styles/dart/lib/hero_details_component.css new file mode 100755 index 0000000000..6e4cd2bb26 --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/hero_details_component.css @@ -0,0 +1,32 @@ +/* #docregion import */ +/* pub build fails on + @ import 'hero_details_box.css'; + See https://github.com/angular/angular/issues/8518 */ + +@import '/packages/component_styles/hero_details_box.css'; +/* #enddocregion import */ + +/* #docregion host */ +:host { + display: block; + border: 1px solid black; +} +/* #enddocregion host */ + +/* #docregion hostfunction */ +:host(.active) { + border-width: 3px; +} +/* #enddocregion hostfunction */ + +/* #docregion hostcontext */ +:host-context(.theme-light) h2 { + background-color: #eef; +} +/* #enddocregion hostcontext */ + +/* #docregion deep */ +:host /deep/ h3 { + font-style: italic; +} +/* #enddocregion deep */ diff --git a/public/docs/_examples/component-styles/dart/lib/hero_details_component.dart b/public/docs/_examples/component-styles/dart/lib/hero_details_component.dart new file mode 100755 index 0000000000..023cc1c170 --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/hero_details_component.dart @@ -0,0 +1,18 @@ +import 'package:angular2/core.dart'; +import 'hero.dart'; +import 'hero_team_component.dart'; + +// #docregion styleurls +@Component( + selector: 'hero-details', + template: ''' +

{{hero.name}}

+ + ''', + styleUrls: const ['hero_details_component.css'], + directives: const [HeroTeamComponent]) +class HeroDetailsComponent { + // #enddocregion styleurls + @Input() Hero hero; + // #docregion styleurls +} diff --git a/public/docs/_examples/component-styles/dart/lib/hero_team_component.css b/public/docs/_examples/component-styles/dart/lib/hero_team_component.css new file mode 100755 index 0000000000..b87679886b --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/hero_team_component.css @@ -0,0 +1,3 @@ +li { + list-style-type: square; +} diff --git a/public/docs/_examples/component-styles/dart/lib/hero_team_component.dart b/public/docs/_examples/component-styles/dart/lib/hero_team_component.dart new file mode 100755 index 0000000000..ec8323b633 --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/hero_team_component.dart @@ -0,0 +1,17 @@ +import 'package:angular2/core.dart'; +import 'hero.dart'; + +// #docregion stylelink +@Component( + selector: 'hero-team', + template: ''' + +

Team

+ ''') +class HeroTeamComponent { + @Input() Hero hero; +} diff --git a/public/docs/_examples/component-styles/dart/lib/quest_summary_component.css b/public/docs/_examples/component-styles/dart/lib/quest_summary_component.css new file mode 100755 index 0000000000..207fa981dd --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/quest_summary_component.css @@ -0,0 +1,5 @@ +:host { + display: block; + background-color: green; + color: white; +} diff --git a/public/docs/_examples/component-styles/dart/lib/quest_summary_component.dart b/public/docs/_examples/component-styles/dart/lib/quest_summary_component.dart new file mode 100755 index 0000000000..dbfe8d99d0 --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/quest_summary_component.dart @@ -0,0 +1,18 @@ +// #docplaster +import 'package:angular2/core.dart'; + +// #docregion +@Component( + selector: 'quest-summary', +// #docregion urls + templateUrl: 'quest_summary_component.html', + styleUrls: const ['quest_summary_component.css']) +// #enddocregion urls +class QuestSummaryComponent {} +// #enddocregion +/* +// #docregion encapsulation.native + // warning: few browsers support shadow DOM encapsulation at this time + encapsulation: ViewEncapsulation.Native + // #enddocregion encapsulation.native +*/ diff --git a/public/docs/_examples/component-styles/dart/lib/quest_summary_component.html b/public/docs/_examples/component-styles/dart/lib/quest_summary_component.html new file mode 100755 index 0000000000..ace27d2a1c --- /dev/null +++ b/public/docs/_examples/component-styles/dart/lib/quest_summary_component.html @@ -0,0 +1 @@ +

No quests in progress

diff --git a/public/docs/_examples/component-styles/dart/pubspec.yaml b/public/docs/_examples/component-styles/dart/pubspec.yaml new file mode 100755 index 0000000000..39769cb7e5 --- /dev/null +++ b/public/docs/_examples/component-styles/dart/pubspec.yaml @@ -0,0 +1,15 @@ +# #docregion +name: component_styles +description: Component Styles example +version: 0.0.1 +environment: + sdk: '>=1.13.0 <2.0.0' +dependencies: + angular2: 2.0.0-beta.17 + browser: ^0.10.0 + dart_to_js_script_rewriter: ^1.0.1 +transformers: +- angular2: + platform_directives: 'package:angular2/common.dart#COMMON_DIRECTIVES' + entry_points: web/main.dart +- dart_to_js_script_rewriter diff --git a/public/docs/_examples/component-styles/dart/web/index.html b/public/docs/_examples/component-styles/dart/web/index.html new file mode 100755 index 0000000000..a74d581227 --- /dev/null +++ b/public/docs/_examples/component-styles/dart/web/index.html @@ -0,0 +1,21 @@ + + + + Component Styles + + + + + + + + +

External H1 Title for E2E test

+ + + + + + diff --git a/public/docs/_examples/component-styles/dart/web/main.dart b/public/docs/_examples/component-styles/dart/web/main.dart new file mode 100755 index 0000000000..536b8c155a --- /dev/null +++ b/public/docs/_examples/component-styles/dart/web/main.dart @@ -0,0 +1,6 @@ +import 'package:angular2/platform/browser.dart'; +import 'package:component_styles/hero_app_component.dart'; + +main() { + bootstrap(HeroAppComponent); +} diff --git a/public/docs/_examples/component-styles/ts/app/hero-app.component.ts b/public/docs/_examples/component-styles/ts/app/hero-app.component.ts index ebfb7241a4..b196584abb 100644 --- a/public/docs/_examples/component-styles/ts/app/hero-app.component.ts +++ b/public/docs/_examples/component-styles/ts/app/hero-app.component.ts @@ -11,8 +11,8 @@ import { HeroAppMainComponent } from './hero-app-main.component'; styles: ['h1 { font-weight: normal; }'], directives: [HeroAppMainComponent] }) -// #enddocregion export class HeroAppComponent { +// #enddocregion hero = new Hero( 'Human Torch', ['Mister Fantastic', 'Invisible Woman', 'Thing'] @@ -21,5 +21,6 @@ export class HeroAppComponent { @HostBinding('class') get themeClass() { return 'theme-light'; } - +// #docregion } +// #enddocregion diff --git a/public/docs/_examples/component-styles/ts/app/hero-controls.component.ts b/public/docs/_examples/component-styles/ts/app/hero-controls.component.ts index 4abfc369b2..5d293596d2 100644 --- a/public/docs/_examples/component-styles/ts/app/hero-controls.component.ts +++ b/public/docs/_examples/component-styles/ts/app/hero-controls.component.ts @@ -17,7 +17,6 @@ import { Hero } from './hero'; }) // #enddocregion inlinestyles export class HeroControlsComponent { - @Input() hero: Hero; activate() { diff --git a/public/docs/_examples/component-styles/ts/app/hero-details.component.ts b/public/docs/_examples/component-styles/ts/app/hero-details.component.ts index f44984cfbd..f530ec0757 100644 --- a/public/docs/_examples/component-styles/ts/app/hero-details.component.ts +++ b/public/docs/_examples/component-styles/ts/app/hero-details.component.ts @@ -14,7 +14,7 @@ import { HeroTeamComponent } from './hero-team.component'; directives: [HeroTeamComponent] }) export class HeroDetailsComponent { -// #enddocregion styleurls - - @Input() hero:Hero; + // #enddocregion styleurls + @Input() hero: Hero; + // #docregion styleurls } diff --git a/public/docs/_examples/component-styles/ts/app/quest-summary.component.html b/public/docs/_examples/component-styles/ts/app/quest-summary.component.html index abf63c2542..ace27d2a1c 100644 --- a/public/docs/_examples/component-styles/ts/app/quest-summary.component.html +++ b/public/docs/_examples/component-styles/ts/app/quest-summary.component.html @@ -1 +1 @@ -No quests in progress +

No quests in progress

diff --git a/public/docs/_examples/component-styles/ts/app/quest-summary.component.ts b/public/docs/_examples/component-styles/ts/app/quest-summary.component.ts index ba363b303e..9952702ddf 100644 --- a/public/docs/_examples/component-styles/ts/app/quest-summary.component.ts +++ b/public/docs/_examples/component-styles/ts/app/quest-summary.component.ts @@ -3,7 +3,6 @@ import { Component, ViewEncapsulation } from '@angular/core'; // #docregion - @Component({ moduleId: module.id, selector: 'quest-summary', @@ -11,6 +10,8 @@ import { Component, ViewEncapsulation } from '@angular/core'; templateUrl: 'quest-summary.component.html', styleUrls: ['quest-summary.component.css'] // #enddocregion urls +}) +export class QuestSummaryComponent { } // #enddocregion /* // #docregion encapsulation.native @@ -18,7 +19,3 @@ import { Component, ViewEncapsulation } from '@angular/core'; encapsulation: ViewEncapsulation.Native // #enddocregion encapsulation.native */ -// #docregion -}) -export class QuestSummaryComponent { } -// #enddocregion diff --git a/public/docs/dart/latest/_util-fns.jade b/public/docs/dart/latest/_util-fns.jade index ee1b718ad3..ffc0ae6fc0 100644 --- a/public/docs/dart/latest/_util-fns.jade +++ b/public/docs/dart/latest/_util-fns.jade @@ -3,6 +3,8 @@ include ../../../_includes/_util-fns //- See the _util-fns file included above for a description of the use of these variables. - var _docsFor = 'dart'; - var _decorator = 'annotation'; +- var _array = 'list'; +- var _an_array = 'a list'; - var _priv = '_'; mixin liveExampleLink(linkText, exampleUrlPartName) diff --git a/public/docs/dart/latest/guide/component-styles.jade b/public/docs/dart/latest/guide/component-styles.jade index f8df2a84a6..71507a7d01 100644 --- a/public/docs/dart/latest/guide/component-styles.jade +++ b/public/docs/dart/latest/guide/component-styles.jade @@ -1 +1,36 @@ -!= partial("../../../_includes/_ts-temp") \ No newline at end of file +extends ../../../ts/latest/guide/component-styles.jade + +block includes + include ../_util-fns + +//- TODO: consider adding material equivalent to TS Appendices 1 & 2 if relevant. + +block style-url + :marked + Note that the URLs in `styleUrls` are relative to the component. + +block module-bundlers + //- TODO: determine if an equivalent of the TS material is relevant for Dart. + //- Leaving empty for now. + +block css-import-url + :marked + In *this* case the URL is relative to the CSS file into which we are importing. + .alert.is-important + :marked + URLs are currently not interpreted in this way, see + [issue 8518](href="https://github.com/angular/angular/issues/8518"). + Until this issue is fixed, absolute package-reference style URLs must + be given as is illustrated below. + +block module-id + p. + Thankfully, this is the default interpretation of relative URLs in + Angular2 for Dart: + +makeExample('component-styles/ts/app/quest-summary.component.ts', 'urls')(format='.') + :marked + Note that special measures must be taken in Angular2 for TypeScript, if + relative URLs are to have the same interpretation. See + [here](../../../ts/latest/guide/component-styles.html#!#relative-urls) + for details. + diff --git a/public/docs/ts/latest/_util-fns.jade b/public/docs/ts/latest/_util-fns.jade index 05c8256082..1dd1b7860d 100644 --- a/public/docs/ts/latest/_util-fns.jade +++ b/public/docs/ts/latest/_util-fns.jade @@ -2,8 +2,7 @@ include ../../../_includes/_util-fns //- See the _util-fns file included above for a description of the use of these variables. - var _docsFor = 'ts'; -- var _decorator = 'decorator'; -- var _priv = ''; +//- Other values match the defaults. mixin liveExampleLink(linkText, exampleUrlPartName) a(href='/resources/live-examples/#{exampleUrlPartName}/ts/plnkr.html')= linkText diff --git a/public/docs/ts/latest/guide/component-styles.jade b/public/docs/ts/latest/guide/component-styles.jade index 6a71bc3af5..499dc7ed1a 100644 --- a/public/docs/ts/latest/guide/component-styles.jade +++ b/public/docs/ts/latest/guide/component-styles.jade @@ -1,4 +1,5 @@ -include ../_util-fns +block includes + include ../_util-fns :marked Angular 2 applications are styled with regular CSS. That means we can apply @@ -14,13 +15,13 @@ include ../_util-fns * [Using Component Styles](#using-component-styles) * [Special selectors](#special-selectors) - * [Loading Styles into Components](#loading-style) - * [Controlling View Encapsulation: Emulated, Native, and None](#controlling-view-encapsulation-native-emulated-and-none) + * [Loading Styles into Components](#loading-styles) + * [Controlling View Encapsulation: Emulated, Native, and None](#view-encapsulation) * [Appendix 1: Inspecting the generated runtime component styles](#inspect-generated-css) * [Appendix 2: Loading Styles with Relative URLs](#relative-urls) - - **[Run the live code](/resources/live-examples/component-styles/ts/plnkr.html) - shown in this chapter.** +p + | #[+liveExampleLink2('Run the live example', 'component-styles')]  + | of the code shown in this chapter. .l-main-section :marked @@ -31,7 +32,7 @@ include ../_util-fns specifying any selectors, rules, and media queries that we need. One way to do this is to set the `styles` property in the component metadata. - The `styles` property takes an array of strings that contain CSS code. + The `styles` property takes #{_an_array} of strings that contain CSS code. Usually we give it one string as in this example: +makeExample('component-styles/ts/app/hero-app.component.ts')(format='.') @@ -40,7 +41,7 @@ include ../_util-fns Component styles differ from traditional, global styles in a couple of ways. Firstly, the selectors we put into a component's styles *only apply withing the template - of that component*. The `h1 { }` selector in the example above only applies to the `

` tag + of that component*. The `h1` selector in the example above only applies to the `

` tag in the template of `HeroAppComponent`. Any `

` elements elsewhere in the application are unaffected. @@ -65,7 +66,7 @@ a(id="special-selectors") ## Special selectors Component styles have a few special *selectors* from the world of - shadow DOM style scoping. + [shadow DOM style scoping](https://www.w3.org/TR/css-scoping-1): ### :host @@ -122,7 +123,7 @@ a(id="special-selectors") :marked The `/deep/` and `>>>` selectors should only be used with **emulated** view encapsulation. This is the default and it is what we use most of the time. See the - [Controlling View Encapsulation](#controlling-view-encapsulation-native-emulated-and-none) + [Controlling View Encapsulation](#view-encapsulation) section for more details. a(id='loading-styles') @@ -139,8 +140,8 @@ a(id='loading-styles') ### Styles in Metadata - We can add a `styles` array property to the `@Component` decorator. - Each string in the array (usually just one string) defines the css. + We can add a `styles` #{_array} property to the `@Component` #{_decorator}. + Each string in the #{_array} (usually just one string) defines the CSS. +makeExample('component-styles/ts/app/hero-app.component.ts') @@ -156,37 +157,42 @@ a(id='loading-styles') ### Style URLs in Metadata We can load styles from external CSS files by adding a `styleUrls` attribute - into a component's `@Component` or `@View` decorator: + into a component's `@Component` or `@View` #{_decorator}: +makeExample('component-styles/ts/app/hero-details.component.ts', 'styleurls') - -.alert.is-important - :marked - The URL is ***relative to the application root*** which is usually the - location of the `index.html` web page that hosts the application. - The style file URL is *not* relative to the component file. - That's why the example URL begins `app/`. - See [Appendix 2](#relative-urls) to specify a URL relative to the component file. - -.l-sub-section - :marked - Users of module bundlers like Webpack may also use the `styles` attribute to load - styles from external files at build time. They could write: - - `styles: [require('my.component.css')]` - We set the `styles` property, **not** `styleUrls` property! The module bundler is loading the CSS strings, not Angular. - Angular only sees the CSS strings *after* the bundler loads them. To Angular it is as if - we wrote the `styles` array by hand. - Refer to the module bundler's documentation for information on loading CSS in this manner. +block style-url + .alert.is-important + :marked + The URL is ***relative to the application root*** which is usually the + location of the `index.html` web page that hosts the application. + The style file URL is *not* relative to the component file. + That's why the example URL begins `app/`. + See [Appendix 2](#relative-urls) to specify a URL relative to the + component file. + +block module-bundlers + .l-sub-section + :marked + Users of module bundlers like Webpack may also use the `styles` attribute + to load styles from external files at build time. They could write: + + `styles: [require('my.component.css')]` + + We set the `styles` property, **not** `styleUrls` property! The module + bundler is loading the CSS strings, not Angular. + Angular only sees the CSS strings *after* the bundler loads them. + To Angular it is as if we wrote the `styles` array by hand. + Refer to the module bundler's documentation for information on + loading CSS in this manner. :marked ### Template Link Tags We can also embed `` tags into the component's HTML template. - As with `styleUrls`, the link tag's `href` URL is relative to the HTML host page of the application, - not relative to the component file. + As with `styleUrls`, the link tag's `href` URL is relative to the + application root, not relative to the component file. +makeExample('component-styles/ts/app/hero-team.component.ts', 'stylelink') @@ -196,10 +202,13 @@ a(id='loading-styles') We can also import CSS files into our CSS files by using the standard CSS [`@import` rule](https://developer.mozilla.org/en/docs/Web/CSS/@import). - In *this* case the URL is relative to the CSS file into which we are importing. +block css-import-url + :marked + In *this* case the URL is relative to the CSS file into which we are importing. +makeExample('component-styles/ts/app/hero-details.component.css', 'import', 'app/hero-details.component.css (excerpt)') - + +a#view-encapsulation .l-main-section :marked ## Controlling View Encapsulation: Native, Emulated, and None @@ -227,13 +236,14 @@ a(id='loading-styles') Set the components encapsulation mode using the `encapsulation` property in the component metadata: +makeExample('component-styles/ts/app/quest-summary.component.ts', 'encapsulation.native')(format='.') + :marked `Native` view encapsulation only works on [browsers that have native support for Shadow DOM](http://caniuse.com/#feat=shadowdom). The support is still limited, which is why `Emulated` view encapsulation is the default mode and recommended in most cases. -a(id="inspect-generated-css") +a#inspect-generated-css .l-main-section :marked ## Appendix 1: Inspecting The CSS Generated in Emulated View Encapsulation @@ -283,7 +293,7 @@ code-example(format=""). We'll likely live with *emulated* mode until shadow DOM gains traction. -a(id="relative-urls") +a#relative-urls .l-main-section :marked ## Appendix 2: Loading Styles with Relative URLs @@ -294,54 +304,61 @@ code-example(format=''). quest-summary.component.ts quest-summary.component.html quest-summary.component.css + :marked We include the template and CSS files by setting the `templateUrl` and `styleUrls` metadata properties respectively. Because these files are co-located with the component, it would be nice to refer to them by name without also having to specify a path back to the root of the application. - - We'd *prefer* to write this: -+makeExample('component-styles/ts/app/quest-summary.component.ts', 'urls')(format='.') -:marked - We can't do that by default. Angular can't find the files and throws an error: - `EXCEPTION: Failed to load quest-summary.component.html` - - Why can't Angular calculate the HTML and CSS URLs from the component file's location? - - Unfortunately, that location is not readily known. - Angular apps can be loaded in many ways: from individual files, from SystemJS packages, or - from CommonJS packages, to name a few. - With this diversity of load strategies, it's not easy to tell at runtime where these files actually reside. - - The only location Angular can be sure of is the URL of the `index.html` home page. - So by default it resolves template and style paths relative to the URL of `index.html`. - That's why we previously wrote our CSS file URLs with an `app/` base path prefix. - - Although this works with any code loading scheme, it is very inconvenient. - We move file folders around all the time during the evolution of our applications. - It's no fun patching the style and template URLs when we do. - - ### *moduleId* - - We can change the way Angular calculates the full URL be setting the component metadata's `moduleId` property. - - If we knew the component file's base path, we'd set `moduleId` to that and - let Angular construct the full URL from this base path plus the CSS and template file names. - - Our challenge is to calculate the base path with minimal effort. - If it's too hard, we shouldn't bother; we should just write the full path to the root and move on. - - Fortunately, *certain* module loaders make it easy. - SystemJS (starting in v.0.19.19) sets a special `__moduleName` variable to the URL of the component file. -.alert.is-important +block module-id :marked - Caution: we currently regard the *__moduleName* feature as experimental. -:marked - Now it's trivial to set the `moduleId` to the `__moduleName` and write module-relative paths for style and template URLs. - -+makeExample('component-styles/ts/app/quest-summary.component.ts','', 'app/quest-summary.component.ts') + We'd *prefer* to write this: + + +makeExample('component-styles/ts/app/quest-summary.component.ts', 'urls')(format='.') -.l-sub-section :marked - With a module bundler like Webpack we are more likely to set the `styles` and `template` properties with the bundler's - `require` mechanism rather than bother with `styleUrls` and `templateUrl`. + We can't do that by default. Angular can't find the files and throws an error: + + `EXCEPTION: Failed to load quest-summary.component.html` + + Why can't Angular calculate the HTML and CSS URLs from the component file's location? + + Unfortunately, that location is not readily known. + Angular apps can be loaded in many ways: from individual files, from SystemJS packages, or + from CommonJS packages, to name a few. + With this diversity of load strategies, it's not easy to tell at runtime where these files actually reside. + + The only location Angular can be sure of is the URL of the `index.html` home page. + So by default it resolves template and style paths relative to the URL of `index.html`. + That's why we previously wrote our CSS file URLs with an `app/` base path prefix. + + Although this works with any code loading scheme, it is very inconvenient. + We move file folders around all the time during the evolution of our applications. + It's no fun patching the style and template URLs when we do. + + ### *moduleId* + + We can change the way Angular calculates the full URL be setting the component metadata's `moduleId` property. + + If we knew the component file's base path, we'd set `moduleId` to that and + let Angular construct the full URL from this base path plus the CSS and template file names. + + Our challenge is to calculate the base path with minimal effort. + If it's too hard, we shouldn't bother; we should just write the full path to the root and move on. + + Fortunately, *certain* module loaders make it easy. + SystemJS (starting in v.0.19.19) sets a special `__moduleName` variable to the URL of the component file. + + .alert.is-important + :marked + Caution: we currently regard the *__moduleName* feature as experimental. + + :marked + Now it's trivial to set the `moduleId` to the `__moduleName` and write module-relative paths for style and template URLs. + + +makeExample('component-styles/ts/app/quest-summary.component.ts','', 'app/quest-summary.component.ts') + + .l-sub-section + :marked + With a module bundler like Webpack we are more likely to set the `styles` and `template` properties with the bundler's + `require` mechanism rather than bother with `styleUrls` and `templateUrl`.