docs(dev guide): Update 'Component Styles' prose (#1320)
Reowork Ts prose and add Dart prose/code + Updates to docs and example code (Starting point for Dart code was taken from #1171.)
This commit is contained in:
parent
6d80a42bea
commit
ef66e38e54
|
@ -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 = '';
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
class Hero {
|
||||
bool active = false;
|
||||
|
||||
final String name;
|
||||
final List<String> team;
|
||||
|
||||
Hero(this.name, this.team);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import 'package:angular2/core.dart';
|
||||
import 'hero.dart';
|
||||
import 'hero_app_main_component.dart';
|
||||
|
||||
// #docregion
|
||||
@Component(
|
||||
selector: 'hero-app',
|
||||
template: '''
|
||||
<h1>Tour of Heroes</h1>
|
||||
<hero-app-main [hero]="hero"></hero-app-main>''',
|
||||
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
|
||||
}
|
|
@ -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: '''
|
||||
<quest-summary></quest-summary>
|
||||
<hero-details [hero]="hero" [class.active]="hero.active">
|
||||
<hero-controls [hero]="hero"></hero-controls>
|
||||
</hero-details>''',
|
||||
directives: const [
|
||||
HeroDetailsComponent,
|
||||
HeroControlsComponent,
|
||||
QuestSummaryComponent
|
||||
])
|
||||
class HeroAppMainComponent {
|
||||
@Input() Hero hero;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import 'package:angular2/core.dart';
|
||||
import 'hero.dart';
|
||||
|
||||
// #docregion inlinestyles
|
||||
@Component(
|
||||
selector: 'hero-controls',
|
||||
template: '''
|
||||
<style>
|
||||
button {
|
||||
background-color: white;
|
||||
border: 1px solid #777;
|
||||
}
|
||||
</style>
|
||||
<h3>Controls</h3>
|
||||
<button (click)="activate()">Activate</button>''')
|
||||
class HeroControlsComponent {
|
||||
@Input()
|
||||
Hero hero;
|
||||
|
||||
void activate() {
|
||||
hero.active = true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
:host {
|
||||
padding: 10px;
|
||||
}
|
||||
h3 {
|
||||
background-color: yellow;
|
||||
}
|
|
@ -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 */
|
|
@ -0,0 +1,18 @@
|
|||
import 'package:angular2/core.dart';
|
||||
import 'hero.dart';
|
||||
import 'hero_team_component.dart';
|
||||
|
||||
// #docregion styleurls
|
||||
@Component(
|
||||
selector: 'hero-details',
|
||||
template: '''
|
||||
<h2>{{hero.name}}</h2>
|
||||
<hero-team [hero]=hero></hero-team>
|
||||
<ng-content></ng-content>''',
|
||||
styleUrls: const ['hero_details_component.css'],
|
||||
directives: const [HeroTeamComponent])
|
||||
class HeroDetailsComponent {
|
||||
// #enddocregion styleurls
|
||||
@Input() Hero hero;
|
||||
// #docregion styleurls
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
li {
|
||||
list-style-type: square;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import 'package:angular2/core.dart';
|
||||
import 'hero.dart';
|
||||
|
||||
// #docregion stylelink
|
||||
@Component(
|
||||
selector: 'hero-team',
|
||||
template: '''
|
||||
<link rel="stylesheet" href="hero_team_component.css">
|
||||
<h3>Team</h3>
|
||||
<ul>
|
||||
<li *ngFor="let member of hero.team">
|
||||
{{member}}
|
||||
</li>
|
||||
</ul>''')
|
||||
class HeroTeamComponent {
|
||||
@Input() Hero hero;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
:host {
|
||||
display: block;
|
||||
background-color: green;
|
||||
color: white;
|
||||
}
|
|
@ -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
|
||||
*/
|
|
@ -0,0 +1 @@
|
|||
<p>No quests in progress</p>
|
|
@ -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
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Component Styles</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
|
||||
<script defer src="main.dart" type="application/dart"></script>
|
||||
<script defer src="packages/browser/dart.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 style="visibility: hidden;">External H1 Title for E2E test</h1>
|
||||
<hero-app></hero-app>
|
||||
<button style="visibility: hidden;">External button for E2E test</button>
|
||||
<ul style="visibility: hidden;">
|
||||
<li>External list for E2E test</li>
|
||||
</ul>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,6 @@
|
|||
import 'package:angular2/platform/browser.dart';
|
||||
import 'package:component_styles/hero_app_component.dart';
|
||||
|
||||
main() {
|
||||
bootstrap(HeroAppComponent);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -17,7 +17,6 @@ import { Hero } from './hero';
|
|||
})
|
||||
// #enddocregion inlinestyles
|
||||
export class HeroControlsComponent {
|
||||
|
||||
@Input() hero: Hero;
|
||||
|
||||
activate() {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
No quests in progress
|
||||
<p>No quests in progress</p>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1 +1,36 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
||||
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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 `<h1>` tag
|
||||
of that component*. The `h1` selector in the example above only applies to the `<h1>` tag
|
||||
in the template of `HeroAppComponent`. Any `<h1>` 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
|
||||
<a href="https://www.w3.org/TR/css-scoping-1/" target="_blank">shadow DOM style scoping</a>.
|
||||
[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 `<link>` 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`.
|
||||
|
|
Loading…
Reference in New Issue