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)
|
//- preceded by the article "a". (E.g., will be "annotation" for Dart)
|
||||||
- var _decorator = 'decorator';
|
- 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 '_'.
|
//- Used to prefix identifiers that are private. In Dart this will be '_'.
|
||||||
- var _priv = '';
|
- 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; }'],
|
styles: ['h1 { font-weight: normal; }'],
|
||||||
directives: [HeroAppMainComponent]
|
directives: [HeroAppMainComponent]
|
||||||
})
|
})
|
||||||
// #enddocregion
|
|
||||||
export class HeroAppComponent {
|
export class HeroAppComponent {
|
||||||
|
// #enddocregion
|
||||||
hero = new Hero(
|
hero = new Hero(
|
||||||
'Human Torch',
|
'Human Torch',
|
||||||
['Mister Fantastic', 'Invisible Woman', 'Thing']
|
['Mister Fantastic', 'Invisible Woman', 'Thing']
|
||||||
|
@ -21,5 +21,6 @@ export class HeroAppComponent {
|
||||||
@HostBinding('class') get themeClass() {
|
@HostBinding('class') get themeClass() {
|
||||||
return 'theme-light';
|
return 'theme-light';
|
||||||
}
|
}
|
||||||
|
// #docregion
|
||||||
}
|
}
|
||||||
|
// #enddocregion
|
||||||
|
|
|
@ -17,7 +17,6 @@ import { Hero } from './hero';
|
||||||
})
|
})
|
||||||
// #enddocregion inlinestyles
|
// #enddocregion inlinestyles
|
||||||
export class HeroControlsComponent {
|
export class HeroControlsComponent {
|
||||||
|
|
||||||
@Input() hero: Hero;
|
@Input() hero: Hero;
|
||||||
|
|
||||||
activate() {
|
activate() {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { HeroTeamComponent } from './hero-team.component';
|
||||||
directives: [HeroTeamComponent]
|
directives: [HeroTeamComponent]
|
||||||
})
|
})
|
||||||
export class HeroDetailsComponent {
|
export class HeroDetailsComponent {
|
||||||
// #enddocregion styleurls
|
// #enddocregion styleurls
|
||||||
|
@Input() hero: Hero;
|
||||||
@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';
|
import { Component, ViewEncapsulation } from '@angular/core';
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
moduleId: module.id,
|
moduleId: module.id,
|
||||||
selector: 'quest-summary',
|
selector: 'quest-summary',
|
||||||
|
@ -11,6 +10,8 @@ import { Component, ViewEncapsulation } from '@angular/core';
|
||||||
templateUrl: 'quest-summary.component.html',
|
templateUrl: 'quest-summary.component.html',
|
||||||
styleUrls: ['quest-summary.component.css']
|
styleUrls: ['quest-summary.component.css']
|
||||||
// #enddocregion urls
|
// #enddocregion urls
|
||||||
|
})
|
||||||
|
export class QuestSummaryComponent { }
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
/*
|
/*
|
||||||
// #docregion encapsulation.native
|
// #docregion encapsulation.native
|
||||||
|
@ -18,7 +19,3 @@ import { Component, ViewEncapsulation } from '@angular/core';
|
||||||
encapsulation: ViewEncapsulation.Native
|
encapsulation: ViewEncapsulation.Native
|
||||||
// #enddocregion encapsulation.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.
|
//- See the _util-fns file included above for a description of the use of these variables.
|
||||||
- var _docsFor = 'dart';
|
- var _docsFor = 'dart';
|
||||||
- var _decorator = 'annotation';
|
- var _decorator = 'annotation';
|
||||||
|
- var _array = 'list';
|
||||||
|
- var _an_array = 'a list';
|
||||||
- var _priv = '_';
|
- var _priv = '_';
|
||||||
|
|
||||||
mixin liveExampleLink(linkText, exampleUrlPartName)
|
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.
|
//- See the _util-fns file included above for a description of the use of these variables.
|
||||||
- var _docsFor = 'ts';
|
- var _docsFor = 'ts';
|
||||||
- var _decorator = 'decorator';
|
//- Other values match the defaults.
|
||||||
- var _priv = '';
|
|
||||||
|
|
||||||
mixin liveExampleLink(linkText, exampleUrlPartName)
|
mixin liveExampleLink(linkText, exampleUrlPartName)
|
||||||
a(href='/resources/live-examples/#{exampleUrlPartName}/ts/plnkr.html')= linkText
|
a(href='/resources/live-examples/#{exampleUrlPartName}/ts/plnkr.html')= linkText
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
include ../_util-fns
|
block includes
|
||||||
|
include ../_util-fns
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Angular 2 applications are styled with regular CSS. That means we can apply
|
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)
|
* [Using Component Styles](#using-component-styles)
|
||||||
* [Special selectors](#special-selectors)
|
* [Special selectors](#special-selectors)
|
||||||
* [Loading Styles into Components](#loading-style)
|
* [Loading Styles into Components](#loading-styles)
|
||||||
* [Controlling View Encapsulation: Emulated, Native, and None](#controlling-view-encapsulation-native-emulated-and-none)
|
* [Controlling View Encapsulation: Emulated, Native, and None](#view-encapsulation)
|
||||||
* [Appendix 1: Inspecting the generated runtime component styles](#inspect-generated-css)
|
* [Appendix 1: Inspecting the generated runtime component styles](#inspect-generated-css)
|
||||||
* [Appendix 2: Loading Styles with Relative URLs](#relative-urls)
|
* [Appendix 2: Loading Styles with Relative URLs](#relative-urls)
|
||||||
|
p
|
||||||
**[Run the live code](/resources/live-examples/component-styles/ts/plnkr.html)
|
| #[+liveExampleLink2('Run the live example', 'component-styles')]
|
||||||
shown in this chapter.**
|
| of the code shown in this chapter.
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
|
@ -31,7 +32,7 @@ include ../_util-fns
|
||||||
specifying any selectors, rules, and media queries that we need.
|
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.
|
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:
|
Usually we give it one string as in this example:
|
||||||
|
|
||||||
+makeExample('component-styles/ts/app/hero-app.component.ts')(format='.')
|
+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.
|
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
|
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
|
in the template of `HeroAppComponent`. Any `<h1>` elements elsewhere in
|
||||||
the application are unaffected.
|
the application are unaffected.
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ a(id="special-selectors")
|
||||||
## Special selectors
|
## Special selectors
|
||||||
|
|
||||||
Component styles have a few special *selectors* from the world of
|
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
|
### :host
|
||||||
|
|
||||||
|
@ -122,7 +123,7 @@ a(id="special-selectors")
|
||||||
:marked
|
:marked
|
||||||
The `/deep/` and `>>>` selectors should only be used with **emulated** view encapsulation.
|
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
|
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.
|
section for more details.
|
||||||
|
|
||||||
a(id='loading-styles')
|
a(id='loading-styles')
|
||||||
|
@ -139,8 +140,8 @@ a(id='loading-styles')
|
||||||
|
|
||||||
### Styles in Metadata
|
### Styles in Metadata
|
||||||
|
|
||||||
We can add a `styles` array property to the `@Component` decorator.
|
We can add a `styles` #{_array} property to the `@Component` #{_decorator}.
|
||||||
Each string in the array (usually just one string) defines the css.
|
Each string in the #{_array} (usually just one string) defines the CSS.
|
||||||
|
|
||||||
+makeExample('component-styles/ts/app/hero-app.component.ts')
|
+makeExample('component-styles/ts/app/hero-app.component.ts')
|
||||||
|
|
||||||
|
@ -156,37 +157,42 @@ a(id='loading-styles')
|
||||||
### Style URLs in Metadata
|
### Style URLs in Metadata
|
||||||
|
|
||||||
We can load styles from external CSS files by adding a `styleUrls` attribute
|
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')
|
+makeExample('component-styles/ts/app/hero-details.component.ts', 'styleurls')
|
||||||
|
|
||||||
.alert.is-important
|
block style-url
|
||||||
:marked
|
.alert.is-important
|
||||||
The URL is ***relative to the application root*** which is usually the
|
:marked
|
||||||
location of the `index.html` web page that hosts the application.
|
The URL is ***relative to the application root*** which is usually the
|
||||||
The style file URL is *not* relative to the component file.
|
location of the `index.html` web page that hosts the application.
|
||||||
That's why the example URL begins `app/`.
|
The style file URL is *not* relative to the component file.
|
||||||
See [Appendix 2](#relative-urls) to specify a URL 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
|
block module-bundlers
|
||||||
:marked
|
.l-sub-section
|
||||||
Users of module bundlers like Webpack may also use the `styles` attribute to load
|
:marked
|
||||||
styles from external files at build time. They could write:
|
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')]`
|
`styles: [require('my.component.css')]`
|
||||||
|
|
||||||
We set the `styles` property, **not** `styleUrls` property! The module bundler is loading the CSS strings, not Angular.
|
We set the `styles` property, **not** `styleUrls` property! The module
|
||||||
Angular only sees the CSS strings *after* the bundler loads them. To Angular it is as if
|
bundler is loading the CSS strings, not Angular.
|
||||||
we wrote the `styles` array by hand.
|
Angular only sees the CSS strings *after* the bundler loads them.
|
||||||
Refer to the module bundler's documentation for information on loading CSS in this manner.
|
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
|
:marked
|
||||||
### Template Link Tags
|
### Template Link Tags
|
||||||
|
|
||||||
We can also embed `<link>` tags into the component's HTML template.
|
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,
|
As with `styleUrls`, the link tag's `href` URL is relative to the
|
||||||
not relative to the component file.
|
application root, not relative to the component file.
|
||||||
|
|
||||||
+makeExample('component-styles/ts/app/hero-team.component.ts', 'stylelink')
|
+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
|
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).
|
[`@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)')
|
+makeExample('component-styles/ts/app/hero-details.component.css', 'import', 'app/hero-details.component.css (excerpt)')
|
||||||
|
|
||||||
|
a#view-encapsulation
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Controlling View Encapsulation: Native, Emulated, and None
|
## 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:
|
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='.')
|
+makeExample('component-styles/ts/app/quest-summary.component.ts', 'encapsulation.native')(format='.')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
`Native` view encapsulation only works on [browsers that have native support
|
`Native` view encapsulation only works on [browsers that have native support
|
||||||
for Shadow DOM](http://caniuse.com/#feat=shadowdom). The support is still limited,
|
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
|
which is why `Emulated` view encapsulation is the default mode and recommended
|
||||||
in most cases.
|
in most cases.
|
||||||
|
|
||||||
a(id="inspect-generated-css")
|
a#inspect-generated-css
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Appendix 1: Inspecting The CSS Generated in Emulated View Encapsulation
|
## 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.
|
We'll likely live with *emulated* mode until shadow DOM gains traction.
|
||||||
|
|
||||||
a(id="relative-urls")
|
a#relative-urls
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Appendix 2: Loading Styles with Relative URLs
|
## Appendix 2: Loading Styles with Relative URLs
|
||||||
|
@ -294,54 +304,61 @@ code-example(format='').
|
||||||
quest-summary.component.ts
|
quest-summary.component.ts
|
||||||
quest-summary.component.html
|
quest-summary.component.html
|
||||||
quest-summary.component.css
|
quest-summary.component.css
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
We include the template and CSS files by setting the `templateUrl` and `styleUrls` metadata properties respectively.
|
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,
|
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.
|
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:
|
block module-id
|
||||||
+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
|
|
||||||
:marked
|
:marked
|
||||||
Caution: we currently regard the *__moduleName* feature as experimental.
|
We'd *prefer* to write this:
|
||||||
: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')
|
+makeExample('component-styles/ts/app/quest-summary.component.ts', 'urls')(format='.')
|
||||||
|
|
||||||
.l-sub-section
|
|
||||||
:marked
|
:marked
|
||||||
With a module bundler like Webpack we are more likely to set the `styles` and `template` properties with the bundler's
|
We can't do that by default. Angular can't find the files and throws an error:
|
||||||
`require` mechanism rather than bother with `styleUrls` and `templateUrl`.
|
|
||||||
|
`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