Merge remote-tracking branch 'remotes/angular.io/master'
# Conflicts: # public/docs/ts/latest/cookbook/dependency-injection.jade # public/docs/ts/latest/guide/component-styles.jade # public/docs/ts/latest/guide/dependency-injection.jade # public/docs/ts/latest/guide/upgrade.jade
This commit is contained in:
commit
633964ac2f
|
@ -1076,7 +1076,7 @@ function getChangedExamplesForCommit(commit, relativePath) {
|
|||
return commit.getDiff().then(function(diffList) {
|
||||
var filePaths = [];
|
||||
diffList.forEach(function (diff) {
|
||||
diff.patches().forEach(function (patch) {
|
||||
diff.patches().then(function (patch) {
|
||||
if (patch.isAdded() || patch.isModified) {
|
||||
var filePath = path.normalize(patch.newFile().path());
|
||||
var isExample = filePath.indexOf(relativePath) >= 0;
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
"minimatch": "^2.0.10",
|
||||
"mkdirp": "^0.5.1",
|
||||
"node-html-encoder": "0.0.2",
|
||||
"nodegit": "0.5.0",
|
||||
"nodegit": "0.13.0",
|
||||
"path": "^0.11.14",
|
||||
"prompt": "^0.2.14",
|
||||
"protractor": "^3.0.0",
|
||||
|
|
|
@ -35,16 +35,11 @@ describe('Dependency Injection Cookbook', function () {
|
|||
expect(sortedHero).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render Hero of the Month when DI deps are defined using provide()', function () {
|
||||
it('should render Hero of the Month', function () {
|
||||
let heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month"]')).get(0);
|
||||
expect(heroOfTheMonth).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render Hero of the Month when DI deps are defined using provide object literal', function () {
|
||||
let heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month 2"]')).get(0);
|
||||
expect(heroOfTheMonth).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render Hero Bios', function () {
|
||||
let heroBios = element.all(by.xpath('//h3[text()="Hero Bios"]')).get(0);
|
||||
expect(heroBios).toBeDefined();
|
||||
|
@ -60,16 +55,11 @@ describe('Dependency Injection Cookbook', function () {
|
|||
expect(magmaPhone).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render Hero-of-the-Month runner-ups when DI deps are defined using provide()', function () {
|
||||
it('should render Hero-of-the-Month runner-ups', function () {
|
||||
let runnersUp = element(by.id('rups1')).getText();
|
||||
expect(runnersUp).toContain('RubberMan, Mr. Nice');
|
||||
});
|
||||
|
||||
it('should render Hero-of-the-Month runner-ups when DI deps are defined using provide object literal', function () {
|
||||
let runnersUp = element(by.id('rups2')).getText();
|
||||
expect(runnersUp).toContain('RubberMan, Mr. Nice');
|
||||
});
|
||||
|
||||
it('should render DateLogger log entry in Hero-of-the-Month', function () {
|
||||
let logs = element.all(by.id('logs')).get(0).getText();
|
||||
expect(logs).toContain('INFO: starting up at');
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
<hero-of-the-month></hero-of-the-month>
|
||||
</div>
|
||||
|
||||
<div class="di-component">
|
||||
<hero-of-the-month-lit></hero-of-the-month-lit>
|
||||
</div>
|
||||
|
||||
<div class="di-component">
|
||||
<h3>Unsorted Heroes</h3>
|
||||
<unsorted-heroes></unsorted-heroes>
|
||||
|
|
|
@ -9,13 +9,10 @@ import { HeroesBaseComponent,
|
|||
import { HighlightDirective } from './highlight.directive';
|
||||
import { ParentFinderComponent } from './parent-finder.component';
|
||||
|
||||
// Object Literal syntax
|
||||
import { HeroOfTheMonthLiteralsComponent } from './hero-of-the-month-literals.component';
|
||||
|
||||
const DIRECTIVES = [
|
||||
HeroBiosComponent, HeroBiosAndContactsComponent,
|
||||
HeroesBaseComponent, SortedHeroesComponent,
|
||||
HeroOfTheMonthComponent, HeroOfTheMonthLiteralsComponent,
|
||||
HeroOfTheMonthComponent,
|
||||
HighlightDirective,
|
||||
ParentFinderComponent
|
||||
];
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
/* tslint:disable:one-line:check-open-brace*/
|
||||
// #docplaster
|
||||
// #docregion opaque-token
|
||||
import { OpaqueToken } from '@angular/core';
|
||||
|
||||
export const TITLE = new OpaqueToken('title');
|
||||
// #enddocregion opaque-token
|
||||
|
||||
// #docregion hero-of-the-month
|
||||
import { Component, Inject } from '@angular/core';
|
||||
|
||||
import { DateLoggerService,
|
||||
MinimalLogger } from './date-logger.service';
|
||||
import { Hero } from './hero';
|
||||
import { HeroService } from './hero.service';
|
||||
import { LoggerService } from './logger.service';
|
||||
import { RUNNERS_UP,
|
||||
runnersUpFactory } from './runners-up';
|
||||
|
||||
// #enddocregion hero-of-the-month
|
||||
// #docregion some-hero
|
||||
const someHero = new Hero(42, 'Magma', 'Had a great month!', '555-555-5555');
|
||||
// #enddocregion some-hero
|
||||
|
||||
const template = `
|
||||
<h3>{{title}}</h3>
|
||||
<div>Winner: <strong>{{heroOfTheMonth.name}}</strong></div>
|
||||
<div>Reason for award: <strong>{{heroOfTheMonth.description}}</strong></div>
|
||||
<div>Runners-up: <strong id="rups2">{{runnersUp}}</strong></div>
|
||||
|
||||
<p>Logs:</p>
|
||||
<div id="logs">
|
||||
<div *ngFor="let log of logs">{{log}}</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// #docregion hero-of-the-month
|
||||
@Component({
|
||||
selector: 'hero-of-the-month-lit',
|
||||
template: template,
|
||||
// #docregion providers-using-object-literals
|
||||
providers: [
|
||||
{provide: Hero, useValue: someHero},
|
||||
{provide: TITLE, useValue: 'Hero of the Month - Object Literals'},
|
||||
{provide: HeroService, useClass: HeroService},
|
||||
{provide: LoggerService, useClass: DateLoggerService},
|
||||
{provide: MinimalLogger, useExisting: LoggerService},
|
||||
{provide: RUNNERS_UP, useFactory: runnersUpFactory(2), deps: [Hero, HeroService]}
|
||||
]
|
||||
// #enddocregion providers-using-object-literals
|
||||
})
|
||||
export class HeroOfTheMonthLiteralsComponent {
|
||||
logs: string[] = [];
|
||||
|
||||
// #docregion ctor-signature
|
||||
constructor(
|
||||
logger: MinimalLogger,
|
||||
public heroOfTheMonth: Hero,
|
||||
@Inject(RUNNERS_UP) public runnersUp: string,
|
||||
@Inject(TITLE) public title: string)
|
||||
// #enddocregion ctor-signature
|
||||
{
|
||||
this.logs = logger.logs;
|
||||
logger.logInfo('starting up');
|
||||
}
|
||||
}
|
||||
// #enddocregion hero-of-the-month
|
|
@ -7,7 +7,7 @@ export const TITLE = new OpaqueToken('title');
|
|||
// #enddocregion opaque-token
|
||||
|
||||
// #docregion hero-of-the-month
|
||||
import { Component, Inject, provide } from '@angular/core';
|
||||
import { Component, Inject } from '@angular/core';
|
||||
|
||||
import { DateLoggerService,
|
||||
MinimalLogger } from './date-logger.service';
|
||||
|
@ -40,20 +40,20 @@ const template = `
|
|||
template: template,
|
||||
providers: [
|
||||
// #docregion use-value
|
||||
provide(Hero, {useValue: someHero}),
|
||||
{ provide: Hero, useValue: someHero },
|
||||
// #docregion provide-opaque-token
|
||||
provide(TITLE, {useValue: 'Hero of the Month'}),
|
||||
{ provide: TITLE, useValue: 'Hero of the Month' },
|
||||
// #enddocregion provide-opaque-token
|
||||
// #enddocregion use-value
|
||||
// #docregion use-class
|
||||
provide(HeroService, {useClass: HeroService}),
|
||||
provide(LoggerService, {useClass: DateLoggerService}),
|
||||
{ provide: HeroService, useClass: HeroService },
|
||||
{ provide: LoggerService, useClass: DateLoggerService },
|
||||
// #enddocregion use-class
|
||||
// #docregion use-existing
|
||||
provide(MinimalLogger, {useExisting: LoggerService}),
|
||||
{ provide: MinimalLogger, useExisting: LoggerService },
|
||||
// #enddocregion use-existing
|
||||
// #docregion provide-opaque-token, use-factory
|
||||
provide(RUNNERS_UP, {useFactory: runnersUpFactory(2), deps: [Hero, HeroService]})
|
||||
{ provide: RUNNERS_UP, useFactory: runnersUpFactory(2), deps: [Hero, HeroService] }
|
||||
// #enddocregion provide-opaque-token, use-factory
|
||||
]
|
||||
})
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// #docregion
|
||||
import { bootstrap } from '@angular/platform-browser-dynamic';
|
||||
import { provide } from '@angular/core';
|
||||
import { XHRBackend } from '@angular/http';
|
||||
import { ROUTER_PROVIDERS } from '@angular/router-deprecated';
|
||||
import { LocationStrategy,
|
||||
|
@ -15,10 +14,9 @@ import { AppComponent } from './app.component';
|
|||
// #docregion bootstrap
|
||||
bootstrap(AppComponent, [
|
||||
ROUTER_PROVIDERS,
|
||||
provide(LocationStrategy,
|
||||
{useClass: HashLocationStrategy}),
|
||||
{ provide: LocationStrategy, useClass: HashLocationStrategy },
|
||||
|
||||
provide(XHRBackend, { useClass: InMemoryBackendService }), // in-mem server
|
||||
provide(SEED_DATA, { useClass: HeroData }) // in-mem server data
|
||||
{ provide: XHRBackend, useClass: InMemoryBackendService }, // in-mem server
|
||||
{ provide: SEED_DATA, useClass: HeroData } // in-mem server data
|
||||
]).catch((err: any) => console.error(err));
|
||||
// #enddocregion bootstrap
|
||||
|
|
|
@ -22,14 +22,17 @@ const DifferentParent = Parent;
|
|||
const provideParent =
|
||||
// #enddocregion provide-parent, provide-the-parent
|
||||
// #docregion provide-parent
|
||||
(component: any, parentType?: any) =>
|
||||
provide(parentType || Parent, { useExisting: forwardRef(() => component) });
|
||||
(component: any, parentType?: any) => {
|
||||
return { provide: parentType || Parent, useExisting: forwardRef(() => component) }
|
||||
};
|
||||
// #enddocregion provide-parent
|
||||
|
||||
// Simpler syntax version that always provides the component in the name of `Parent`.
|
||||
const provideTheParent =
|
||||
// #docregion provide-the-parent
|
||||
(component: any) => provide(Parent, { useExisting: forwardRef(() => component) });
|
||||
(component: any) => {
|
||||
return { provide: Parent, useExisting: forwardRef(() => component) }
|
||||
};
|
||||
// #enddocregion provide-the-parent
|
||||
|
||||
|
||||
|
@ -105,7 +108,7 @@ const templateB = `
|
|||
selector: 'barry',
|
||||
template: templateB,
|
||||
directives: C_DIRECTIVES,
|
||||
providers: [ provide(Parent, { useExisting: forwardRef(() => BarryComponent) }) ]
|
||||
providers: [{ provide: Parent, useExisting: forwardRef(() => BarryComponent) }]
|
||||
})
|
||||
export class BarryComponent implements Parent {
|
||||
name = 'Barry';
|
||||
|
@ -155,7 +158,7 @@ const B_DIRECTIVES = [ BarryComponent, BethComponent, BobComponent ];
|
|||
</div>`,
|
||||
// #enddocregion alex-1
|
||||
// #docregion alex-providers
|
||||
providers: [ provide(Parent, { useExisting: forwardRef(() => AlexComponent) }) ],
|
||||
providers: [{ provide: Parent, useExisting: forwardRef(() => AlexComponent) }],
|
||||
// #enddocregion alex-providers
|
||||
// #docregion alex-1
|
||||
directives: C_DIRECTIVES
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
// #enddocregion appimport
|
||||
|
||||
// #docregion ng2import
|
||||
var provide =
|
||||
ng.core.provide;
|
||||
var bootstrap =
|
||||
ng.platformBrowserDynamic.bootstrap;
|
||||
var LocationStrategy =
|
||||
|
@ -25,10 +23,10 @@
|
|||
bootstrap(app.HeroDIComponent, [app.DataService]);
|
||||
bootstrap(app.HeroDIInlineComponent, [app.DataService]);
|
||||
bootstrap(app.HeroDIInjectComponent, [
|
||||
ng.core.provide('heroName', {useValue: 'Windstorm'})
|
||||
{ provide: 'heroName', useValue: 'Windstorm' }
|
||||
]);
|
||||
bootstrap(app.HeroDIInjectComponent2, [
|
||||
ng.core.provide('heroName', {useValue: 'Bombasto'})
|
||||
{ provide: 'heroName', useValue: 'Bombasto' }
|
||||
]);
|
||||
bootstrap(app.HeroDIInjectAdditionalComponent);
|
||||
bootstrap(app.HeroIOComponent);
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
// #docregion ng2import
|
||||
import { provide }
|
||||
from '@angular/core';
|
||||
import { bootstrap }
|
||||
from '@angular/platform-browser-dynamic';
|
||||
import {
|
||||
|
@ -29,7 +27,7 @@ bootstrap(HeroComponent);
|
|||
bootstrap(HeroLifecycleComponent);
|
||||
bootstrap(HeroDIComponent, [DataService]);
|
||||
bootstrap(HeroDIInjectComponent, [
|
||||
provide('heroName', {useValue: 'Windstorm'})
|
||||
{ provide: 'heroName', useValue: 'Windstorm' }
|
||||
]);
|
||||
bootstrap(AppDIInjectAdditionalComponent);
|
||||
bootstrap(AppIOComponent);
|
||||
|
|
|
@ -27,38 +27,6 @@ class ProviderComponent1 {
|
|||
}
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'provider-2',
|
||||
template: '{{log}}',
|
||||
providers:
|
||||
// #docregion providers-2
|
||||
const [const Provider(Logger, useClass: Logger)]
|
||||
// #enddocregion providers-2
|
||||
)
|
||||
class ProviderComponent2 {
|
||||
String log;
|
||||
|
||||
ProviderComponent2(Logger logger) {
|
||||
logger.log('Hello from logger provided with Provider class and useClass');
|
||||
log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
/// Component just used to ensure that shared E2E tests pass.
|
||||
@Component(
|
||||
selector: 'provider-3',
|
||||
template: '{{log}}',
|
||||
providers: const [const Provider(Logger, useClass: Logger)]
|
||||
)
|
||||
class ProviderComponent3 {
|
||||
String log;
|
||||
|
||||
ProviderComponent3(Logger logger) {
|
||||
logger.log('Hello from logger provided with useClass');
|
||||
log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
/// Component just used to ensure that shared E2E tests pass.
|
||||
@Component(
|
||||
selector: 'provider-3a',
|
||||
|
@ -282,8 +250,6 @@ class ProviderComponent10 implements OnInit {
|
|||
template: '''
|
||||
<h2>Provider variations</h2>
|
||||
<div id="p1"><provider-1></provider-1></div>
|
||||
<div id="p2"><provider-2></provider-2></div>
|
||||
<div id="p3"><provider-3></provider-3></div>
|
||||
<div id="p3a"><provider-3a></provider-3a></div>
|
||||
<div id="p4"><provider-4></provider-4></div>
|
||||
<div id="p5"><provider-5></provider-5></div>
|
||||
|
@ -295,8 +261,6 @@ class ProviderComponent10 implements OnInit {
|
|||
<div id="p10"><provider-10></provider-10></div>''',
|
||||
directives: const [
|
||||
ProviderComponent1,
|
||||
ProviderComponent2,
|
||||
ProviderComponent3,
|
||||
ProviderComponent3a,
|
||||
ProviderComponent4,
|
||||
ProviderComponent5,
|
||||
|
|
|
@ -80,18 +80,8 @@ describe('Dependency Injection Tests', function () {
|
|||
expect(element(by.css('#p1')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P2 (Provider) displays as expected', function () {
|
||||
expectedMsg = 'Hello from logger provided with Provider class and useClass';
|
||||
expect(element(by.css('#p2')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P3 (provide) displays as expected', function () {
|
||||
expectedMsg = 'Hello from logger provided with useClass';
|
||||
expect(element(by.css('#p3')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P3a (provide) displays as expected', function () {
|
||||
expectedMsg = 'Hello from logger provided with {provide: Logger, useClass: Logger}';
|
||||
expectedMsg = 'Hello from logger provided with { provide: Logger, useClass: Logger }';
|
||||
expect(element(by.css('#p3a')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Component } from '@angular/core';
|
|||
import { CarComponent } from './car/car.component';
|
||||
import { HeroesComponent } from './heroes/heroes.component.1';
|
||||
|
||||
import { provide, Inject } from '@angular/core';
|
||||
import { Inject } from '@angular/core';
|
||||
import { APP_CONFIG, AppConfig,
|
||||
HERO_DI_CONFIG } from './app.config';
|
||||
import { Logger } from './logger.service';
|
||||
|
@ -21,7 +21,7 @@ import { Logger } from './logger.service';
|
|||
providers: [
|
||||
Logger,
|
||||
// #docregion providers
|
||||
provide(APP_CONFIG, {useValue: HERO_DI_CONFIG})
|
||||
{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG }
|
||||
// #enddocregion providers
|
||||
]
|
||||
})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
// #docregion imports
|
||||
import { Component, Inject, provide } from '@angular/core';
|
||||
import { Component, Inject } from '@angular/core';
|
||||
|
||||
import { CarComponent } from './car/car.component';
|
||||
import { HeroesComponent } from './heroes/heroes.component';
|
||||
|
@ -37,7 +37,7 @@ import { ProvidersComponent } from './providers.component';
|
|||
providers: [
|
||||
Logger,
|
||||
UserService,
|
||||
provide(APP_CONFIG, {useValue: HERO_DI_CONFIG})
|
||||
{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG }
|
||||
]
|
||||
// #enddocregion providers
|
||||
})
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
// #docregion
|
||||
import { provide } from '@angular/core';
|
||||
|
||||
import { HeroService } from './hero.service';
|
||||
import { Logger } from '../logger.service';
|
||||
import { UserService } from '../user.service';
|
||||
|
@ -13,8 +11,8 @@ let heroServiceFactory = (logger: Logger, userService: UserService) => {
|
|||
|
||||
// #docregion provider
|
||||
export let heroServiceProvider =
|
||||
provide(HeroService, {
|
||||
{ provide: HeroService,
|
||||
useFactory: heroServiceFactory,
|
||||
deps: [Logger, UserService]
|
||||
});
|
||||
};
|
||||
// #enddocregion provider
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
/* tslint:disable:one-line:check-open-brace*/
|
||||
// Examples of provider arrays
|
||||
// #docplaster
|
||||
import { Component, Inject, Injectable,
|
||||
provide, Provider } from '@angular/core';
|
||||
import { Component, Inject, Injectable } from '@angular/core';
|
||||
|
||||
import { APP_CONFIG, AppConfig,
|
||||
HERO_DI_CONFIG } from './app.config';
|
||||
|
@ -30,53 +29,19 @@ export class ProviderComponent1 {
|
|||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
@Component({
|
||||
selector: 'provider-2',
|
||||
template: template,
|
||||
providers:
|
||||
// #docregion providers-2
|
||||
[new Provider(Logger, {useClass: Logger})]
|
||||
// #enddocregion providers-2
|
||||
})
|
||||
export class ProviderComponent2 {
|
||||
log: string;
|
||||
constructor(logger: Logger) {
|
||||
logger.log('Hello from logger provided with Provider class and useClass');
|
||||
this.log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
@Component({
|
||||
selector: 'provider-3',
|
||||
template: template,
|
||||
providers:
|
||||
// #docregion providers-3
|
||||
[provide(Logger, {useClass: Logger})]
|
||||
// #enddocregion providers-3
|
||||
})
|
||||
export class ProviderComponent3 {
|
||||
log: string;
|
||||
constructor(logger: Logger) {
|
||||
logger.log('Hello from logger provided with useClass');
|
||||
this.log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
@Component({
|
||||
selector: 'provider-3a',
|
||||
template: template,
|
||||
providers:
|
||||
// #docregion providers-3a
|
||||
[{provide: Logger, useClass: Logger}]
|
||||
[{ provide: Logger, useClass: Logger }]
|
||||
// #enddocregion providers-3a
|
||||
})
|
||||
export class ProviderComponent3a {
|
||||
log: string;
|
||||
constructor(logger: Logger) {
|
||||
logger.log('Hello from logger provided with {provide: Logger, useClass: Logger}');
|
||||
logger.log('Hello from logger provided with { provide: Logger, useClass: Logger }');
|
||||
this.log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +54,7 @@ class BetterLogger extends Logger {}
|
|||
template: template,
|
||||
providers:
|
||||
// #docregion providers-4
|
||||
[provide(Logger, {useClass: BetterLogger})]
|
||||
[{ provide: Logger, useClass: BetterLogger }]
|
||||
// #enddocregion providers-4
|
||||
})
|
||||
export class ProviderComponent4 {
|
||||
|
@ -119,7 +84,7 @@ class EvenBetterLogger extends Logger {
|
|||
providers:
|
||||
// #docregion providers-5
|
||||
[ UserService,
|
||||
provide(Logger, {useClass: EvenBetterLogger}) ]
|
||||
{ provide: Logger, useClass: EvenBetterLogger }]
|
||||
// #enddocregion providers-5
|
||||
})
|
||||
export class ProviderComponent5 {
|
||||
|
@ -146,7 +111,7 @@ class OldLogger {
|
|||
// #docregion providers-6a
|
||||
[ NewLogger,
|
||||
// Not aliased! Creates two instances of `NewLogger`
|
||||
provide(OldLogger, {useClass: NewLogger}) ]
|
||||
{ provide: OldLogger, useClass: NewLogger}]
|
||||
// #enddocregion providers-6a
|
||||
})
|
||||
export class ProviderComponent6a {
|
||||
|
@ -169,7 +134,7 @@ export class ProviderComponent6a {
|
|||
// #docregion providers-6b
|
||||
[ NewLogger,
|
||||
// Alias OldLogger w/ reference to NewLogger
|
||||
provide(OldLogger, {useExisting: NewLogger}) ]
|
||||
{ provide: OldLogger, useExisting: NewLogger}]
|
||||
// #enddocregion providers-6b
|
||||
})
|
||||
export class ProviderComponent6b {
|
||||
|
@ -197,7 +162,7 @@ let silentLogger = {
|
|||
template: template,
|
||||
providers:
|
||||
// #docregion providers-7
|
||||
[provide(Logger, {useValue: silentLogger})]
|
||||
[{ provide: Logger, useValue: silentLogger }]
|
||||
// #enddocregion providers-7
|
||||
})
|
||||
export class ProviderComponent7 {
|
||||
|
@ -230,11 +195,11 @@ export class ProviderComponent8 {
|
|||
/*
|
||||
// #docregion providers-9-interface
|
||||
// FAIL! Can't use interface as provider token
|
||||
[provide(AppConfig, {useValue: HERO_DI_CONFIG})]
|
||||
[{ provide: AppConfig, useValue: HERO_DI_CONFIG })]
|
||||
// #enddocregion providers-9-interface
|
||||
*/
|
||||
// #docregion providers-9
|
||||
providers: [provide(APP_CONFIG, {useValue: HERO_DI_CONFIG})]
|
||||
providers: [{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG }]
|
||||
// #enddocregion providers-9
|
||||
})
|
||||
export class ProviderComponent9 {
|
||||
|
@ -257,7 +222,7 @@ export class ProviderComponent9 {
|
|||
// Sample providers 1 to 7 illustrate a required logger dependency.
|
||||
// Optional logger, can be null
|
||||
// #docregion import-optional
|
||||
import {Optional} from '@angular/core';
|
||||
import { Optional } from '@angular/core';
|
||||
// #enddocregion import-optional
|
||||
|
||||
let some_message: string = 'Hello from the injected logger';
|
||||
|
@ -286,8 +251,6 @@ export class ProviderComponent10 {
|
|||
template: `
|
||||
<h2>Provider variations</h2>
|
||||
<div id="p1"><provider-1></provider-1></div>
|
||||
<div id="p2"><provider-2></provider-2></div>
|
||||
<div id="p3"><provider-3></provider-3></div>
|
||||
<div id="p3a"><provider-3a></provider-3a></div>
|
||||
<div id="p4"><provider-4></provider-4></div>
|
||||
<div id="p5"><provider-5></provider-5></div>
|
||||
|
@ -300,8 +263,6 @@ export class ProviderComponent10 {
|
|||
`,
|
||||
directives: [
|
||||
ProviderComponent1,
|
||||
ProviderComponent2,
|
||||
ProviderComponent3,
|
||||
ProviderComponent3a,
|
||||
ProviderComponent4,
|
||||
ProviderComponent5,
|
||||
|
|
|
@ -8,7 +8,6 @@ import { bootstrap } from '@angular/platform-browser-dynamic';
|
|||
import { ROUTER_PROVIDERS } from '@angular/router-deprecated';
|
||||
|
||||
// Add these symbols to override the `LocationStrategy`
|
||||
import { provide } from '@angular/core';
|
||||
import { LocationStrategy,
|
||||
HashLocationStrategy } from '@angular/common';
|
||||
|
||||
|
@ -27,7 +26,6 @@ import { AppComponent as ac } from './app.component.2';
|
|||
bootstrap(ac, [
|
||||
// #docregion
|
||||
ROUTER_PROVIDERS,
|
||||
provide(LocationStrategy,
|
||||
{useClass: HashLocationStrategy}) // .../#/crisis-center/
|
||||
{ provide: LocationStrategy, useClass: HashLocationStrategy } // .../#/crisis-center/
|
||||
]);
|
||||
// #enddocregion
|
||||
|
|
|
@ -8,7 +8,6 @@ import { bootstrap } from '@angular/platform-browser-dynamic';
|
|||
import { ROUTER_PROVIDERS } from '@angular/router';
|
||||
|
||||
// Add these symbols to override the `LocationStrategy`
|
||||
import { provide } from '@angular/core';
|
||||
import { LocationStrategy,
|
||||
HashLocationStrategy } from '@angular/common';
|
||||
|
||||
|
@ -27,7 +26,6 @@ import {AppComponent as ac} from './app.component.2';
|
|||
bootstrap(ac, [
|
||||
// #docregion
|
||||
ROUTER_PROVIDERS,
|
||||
provide(LocationStrategy,
|
||||
{useClass: HashLocationStrategy}) // .../#/crisis-center/
|
||||
{ provide: LocationStrategy, useClass: HashLocationStrategy } // .../#/crisis-center/
|
||||
]);
|
||||
// #enddocregion
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// #docplaster
|
||||
// #docregion final
|
||||
// Imports for loading & configuring the in-memory web api
|
||||
import { provide } from '@angular/core';
|
||||
import { XHRBackend } from '@angular/http';
|
||||
|
||||
import { InMemoryBackendService,
|
||||
|
@ -24,7 +23,7 @@ bootstrap(AppComponent, [ HTTP_PROVIDERS ]);
|
|||
// #docregion final
|
||||
bootstrap(AppComponent, [
|
||||
HTTP_PROVIDERS,
|
||||
provide(XHRBackend, { useClass: InMemoryBackendService }), // in-mem server
|
||||
provide(SEED_DATA, { useClass: HeroData }) // in-mem server data
|
||||
{ provide: XHRBackend, useClass: InMemoryBackendService }, // in-mem server
|
||||
{ provide: SEED_DATA, useClass: HeroData } // in-mem server data
|
||||
]);
|
||||
// #enddocregion final
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { AppComponent } from './app.component';
|
||||
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DebugElement, provide } from '@angular/core';
|
||||
import { DebugElement } from '@angular/core';
|
||||
|
||||
import {
|
||||
beforeEach, beforeEachProviders,
|
||||
|
@ -28,8 +28,8 @@ describe('AppComponent', () => {
|
|||
.overrideDirective(AppComponent, RouterLink, MockRouterLink)
|
||||
.overrideDirective(AppComponent, RouterOutlet, MockRouterOutlet)
|
||||
.overrideProviders(AppComponent, [
|
||||
provide(HeroService, {useClass: MockHeroService}),
|
||||
provide(Router, {useClass: MockRouter}),
|
||||
{ provide: HeroService, useClass: MockHeroService},
|
||||
{ provide: Router, useClass: MockRouter},
|
||||
])
|
||||
.createAsync(AppComponent)
|
||||
.then(fix => {
|
||||
|
|
|
@ -13,6 +13,8 @@ import { HeroesComponent } from './heroes.component';
|
|||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
import { HeroService } from './hero.service';
|
||||
|
||||
import { BAG_DIRECTIVES, BAG_PROVIDERS } from './bag';
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: `
|
||||
|
@ -22,12 +24,23 @@ import { HeroService } from './hero.service';
|
|||
<a [routerLink]="['Heroes']">Heroes</a>
|
||||
</nav>
|
||||
<router-outlet></router-outlet>
|
||||
<hr>
|
||||
<h1>Bag-a-specs</h1>
|
||||
<my-if-parent-comp></my-if-parent-comp>
|
||||
<h3>External Template Comp</h3>
|
||||
<external-template-comp></external-template-comp>
|
||||
<h3>Comp With External Template Comp</h3>
|
||||
<comp-w-ext-comp></comp-w-ext-comp>
|
||||
`,
|
||||
/*
|
||||
|
||||
*/
|
||||
styleUrls: ['app/app.component.css'],
|
||||
directives: [RouterLink, RouterOutlet],
|
||||
directives: [RouterLink, RouterOutlet, BAG_DIRECTIVES],
|
||||
providers: [
|
||||
ROUTER_PROVIDERS,
|
||||
HeroService
|
||||
HeroService,
|
||||
BAG_PROVIDERS
|
||||
]
|
||||
})
|
||||
@RouteConfig([
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Tests that show what goes wrong when the tests are incorrectly written or have a problem
|
||||
*/
|
||||
import {
|
||||
BadTemplateUrl, ButtonComp,
|
||||
BadTemplateUrlComp, ButtonComp,
|
||||
ChildChildComp, ChildComp, ChildWithChildComp,
|
||||
ExternalTemplateComp,
|
||||
FancyService, MockFancyService,
|
||||
|
@ -27,7 +27,6 @@ import {
|
|||
|
||||
import { ComponentFixture, TestComponentBuilder } from '@angular/compiler/testing';
|
||||
|
||||
import { provide } from '@angular/core';
|
||||
import { ViewMetadata } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
|
@ -134,7 +133,7 @@ xdescribe('async & inject testing errors', () => {
|
|||
|
||||
it('should fail with an error from a promise',
|
||||
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||
tcb.createAsync(BadTemplateUrl);
|
||||
tcb.createAsync(BadTemplateUrlComp);
|
||||
})));
|
||||
|
||||
itPromise.then(
|
||||
|
@ -145,7 +144,7 @@ xdescribe('async & inject testing errors', () => {
|
|||
}, 10000);
|
||||
|
||||
describe('using beforeEachProviders', () => {
|
||||
beforeEachProviders(() => [provide(FancyService, {useValue: new FancyService()})]);
|
||||
beforeEachProviders(() => [{ provide: FancyService, useValue: new FancyService() }]);
|
||||
|
||||
beforeEach(
|
||||
inject([FancyService], (service: FancyService) => { expect(service.value).toEqual('real value'); }));
|
||||
|
@ -155,7 +154,7 @@ xdescribe('async & inject testing errors', () => {
|
|||
it('should fail when the injector has already been used', () => {
|
||||
patchJasmineBeforeEach();
|
||||
expect(() => {
|
||||
beforeEachProviders(() => [provide(FancyService, {useValue: new FancyService()})]);
|
||||
beforeEachProviders(() => [{ provide: FancyService, useValue: new FancyService() }]);
|
||||
})
|
||||
.toThrowError('beforeEachProviders was called after the injector had been used ' +
|
||||
'in a beforeEach or it block. This invalidates the test injector');
|
||||
|
|
|
@ -25,7 +25,6 @@ import {
|
|||
|
||||
import { ComponentFixture, TestComponentBuilder } from '@angular/compiler/testing';
|
||||
|
||||
import { provide } from '@angular/core';
|
||||
import { ViewMetadata } from '@angular/core';
|
||||
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
@ -116,7 +115,7 @@ describe('using the test injector with the inject helper', () => {
|
|||
|
||||
describe('setting up Providers with FancyService', () => {
|
||||
beforeEachProviders(() => [
|
||||
provide(FancyService, {useValue: new FancyService()})
|
||||
{ provide: FancyService, useValue: new FancyService() }
|
||||
]);
|
||||
|
||||
it('should use FancyService',
|
||||
|
@ -183,7 +182,7 @@ describe('using the test injector with the inject helper', () => {
|
|||
describe('using `withProviders` for per-test provision', () => {
|
||||
it('should inject test-local FancyService for this test',
|
||||
// `withProviders`: set up providers at individual test level
|
||||
withProviders(() => [provide(FancyService, {useValue: {value: 'fake value'}})])
|
||||
withProviders(() => [{ provide: FancyService, useValue: {value: 'fake value' }}])
|
||||
|
||||
// now inject and test
|
||||
.inject([FancyService], (service: FancyService) => {
|
||||
|
@ -314,7 +313,7 @@ describe('test component builder', function() {
|
|||
|
||||
tcb.overrideProviders(
|
||||
TestProvidersComp,
|
||||
[provide(FancyService, {useClass: MockFancyService})]
|
||||
[{ provide: FancyService, useClass: MockFancyService }]
|
||||
)
|
||||
.createAsync(TestProvidersComp)
|
||||
.then(fixture => {
|
||||
|
@ -329,7 +328,7 @@ describe('test component builder', function() {
|
|||
|
||||
tcb.overrideViewProviders(
|
||||
TestViewProvidersComp,
|
||||
[provide(FancyService, {useClass: MockFancyService})]
|
||||
[{ provide: FancyService, useClass: MockFancyService }]
|
||||
)
|
||||
.createAsync(TestViewProvidersComp)
|
||||
.then(fixture => {
|
||||
|
@ -495,7 +494,7 @@ describe('tcb.overrideProviders', () => {
|
|||
|
||||
tcb.overrideProviders(
|
||||
AnotherProvidersComp,
|
||||
[provide(HeroService, {useValue: {}})]
|
||||
[{ provide: HeroService, useValue: {}} ]
|
||||
)
|
||||
.createAsync(AnotherProvidersComp);
|
||||
})));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Based on https://github.com/angular/angular/blob/master/modules/angular2/test/testing/testing_public_spec.ts
|
||||
/* tslint:disable:forin */
|
||||
import { Component, EventEmitter, Injectable, Input, Output,
|
||||
import { Component, EventEmitter, Injectable, Input, Output, Optional,
|
||||
OnInit, OnChanges, OnDestroy, SimpleChange } from '@angular/core';
|
||||
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
@ -13,6 +13,8 @@ import { Observable } from 'rxjs/Rx';
|
|||
export class FancyService {
|
||||
value: string = 'real value';
|
||||
|
||||
getValue() { return this.value; }
|
||||
|
||||
getAsyncValue() { return Promise.resolve('async value'); }
|
||||
|
||||
getObservableValue() { return Observable.of('observable value'); }
|
||||
|
@ -123,20 +125,36 @@ export class TestViewProvidersComp {
|
|||
constructor(private fancyService: FancyService) {}
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'external-template-comp',
|
||||
templateUrl: 'bag-external-template.html'
|
||||
})
|
||||
export class ExternalTemplateComp { }
|
||||
export class ExternalTemplateComp {
|
||||
serviceValue: string;
|
||||
|
||||
constructor(@Optional() private service: FancyService) { }
|
||||
|
||||
ngOnInit() {
|
||||
if (this.service) { this.serviceValue = this.service.getValue(); }
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'comp-w-ext-comp',
|
||||
template: `
|
||||
<h3>comp-w-ext-comp</h3>
|
||||
<external-template-comp></external-template-comp>
|
||||
`,
|
||||
directives: [ExternalTemplateComp]
|
||||
})
|
||||
export class CompWithCompWithExternalTemplate { }
|
||||
|
||||
@Component({
|
||||
selector: 'bad-template-comp',
|
||||
templateUrl: 'non-existant.html'
|
||||
})
|
||||
export class BadTemplateUrl { }
|
||||
export class BadTemplateUrlComp { }
|
||||
|
||||
|
||||
///////// MyIfChildComp ////////
|
||||
|
@ -222,3 +240,16 @@ export class MyIfParentComp implements OnInit {
|
|||
this.toggleLabel = this.showChild ? 'Close' : 'Show';
|
||||
}
|
||||
}
|
||||
|
||||
export const BAG_PROVIDERS = [FancyService];
|
||||
|
||||
export const BAG_DIRECTIVES = [
|
||||
ButtonComp,
|
||||
ChildChildComp, ChildComp, ChildWithChildComp,
|
||||
ExternalTemplateComp, CompWithCompWithExternalTemplate,
|
||||
InputComp,
|
||||
MyIfComp, MyIfChildComp, MyIfParentComp,
|
||||
MockChildComp, MockChildChildComp,
|
||||
ParentComp,
|
||||
TestProvidersComp, TestViewProvidersComp
|
||||
];
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import { DashboardComponent } from './dashboard.component';
|
||||
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { provide } from '@angular/core';
|
||||
|
||||
import {
|
||||
beforeEach, beforeEachProviders,
|
||||
|
@ -74,9 +73,9 @@ describe('DashboardComponent', () => {
|
|||
beforeEachProviders(() => {
|
||||
mockHeroService = new MockHeroService();
|
||||
return [
|
||||
provide(Router, {useClass: MockRouter}),
|
||||
provide(MockRouter, {useExisting: Router}),
|
||||
provide(HeroService, {useValue: mockHeroService})
|
||||
{ provide: Router, useClass: MockRouter},
|
||||
{ provide: MockRouter, useExisting: Router},
|
||||
{ provide: HeroService, useValue: mockHeroService }
|
||||
];
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// See https://github.com/angular/angular/issues/9017
|
||||
import { expect as expectCore} from '@angular/core/testing';
|
||||
import { NgMatchers } from '@angular/platform-browser/testing';
|
||||
|
||||
export function expect(spy: Function): NgMatchers;
|
||||
export function expect(actual: any): NgMatchers;
|
||||
export function expect(actual: any): NgMatchers {
|
||||
return expectCore(actual) as NgMatchers;
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
// #enddocregion import-oninit
|
||||
// #docregion import-route-params
|
||||
import {RouteParams} from '@angular/router-deprecated';
|
||||
import { RouteParams } from '@angular/router-deprecated';
|
||||
// #enddocregion import-route-params
|
||||
|
||||
import { Hero } from './hero';
|
||||
|
|
|
@ -8,8 +8,6 @@ import {
|
|||
|
||||
import { TestComponentBuilder } from '@angular/compiler/testing';
|
||||
|
||||
import { provide } from '@angular/core';
|
||||
|
||||
import {
|
||||
MockBackend,
|
||||
MockConnection } from '@angular/http/testing';
|
||||
|
@ -46,7 +44,7 @@ describe('Http-HeroService (mockBackend)', () => {
|
|||
|
||||
beforeEachProviders(() => [
|
||||
HTTP_PROVIDERS,
|
||||
provide(XHRBackend, {useClass: MockBackend})
|
||||
{ provide: XHRBackend, useClass: MockBackend }
|
||||
]);
|
||||
|
||||
it('can instantiate service when inject service',
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { bootstrap } from '@angular/platform-browser-dynamic';
|
||||
import { AppComponent } from './app.component';
|
||||
import { MyIfParentComp } from './bag';
|
||||
|
||||
bootstrap(AppComponent);
|
||||
bootstrap(MyIfParentComp);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// #docregion
|
||||
import {Pipe, PipeTransform} from '@angular/core';
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
@Pipe({ name: 'my-uppercase' })
|
||||
export class MyUppercasePipe implements PipeTransform {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// #docregion
|
||||
// #docregion depends-on-angular
|
||||
import {Pipe, PipeTransform} from '@angular/core';
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
// #enddocregion depends-on-angular
|
||||
|
||||
@Pipe({ name: 'my-uppercase' })
|
||||
|
|
|
@ -22,7 +22,5 @@
|
|||
|
||||
<body>
|
||||
<my-app>Loading...</my-app>
|
||||
<hr>
|
||||
<my-if-parent-comp>Loading MyIfParentComp ...</my-if-parent-comp>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// #docplaster
|
||||
// #docregion final
|
||||
// Imports for loading & configuring the in-memory web api
|
||||
import { provide } from '@angular/core';
|
||||
import { XHRBackend } from '@angular/http';
|
||||
|
||||
import { InMemoryBackendService, SEED_DATA } from 'angular2-in-memory-web-api';
|
||||
|
@ -23,7 +22,7 @@ bootstrap(AppComponent, [ HTTP_PROVIDERS ]);
|
|||
// #docregion final
|
||||
bootstrap(AppComponent, [
|
||||
HTTP_PROVIDERS,
|
||||
provide(XHRBackend, { useClass: InMemoryBackendService }), // in-mem server
|
||||
provide(SEED_DATA, { useClass: InMemoryDataService }) // in-mem server data
|
||||
{ provide: XHRBackend, useClass: InMemoryBackendService }, // in-mem server
|
||||
{ provide: SEED_DATA, useClass: InMemoryDataService } // in-mem server data
|
||||
]);
|
||||
// #enddocregion final
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// #docregion
|
||||
import { provide } from '@angular/core';
|
||||
import {
|
||||
describe,
|
||||
beforeEach,
|
||||
|
@ -29,11 +28,11 @@ describe('Phone', function() {
|
|||
Phone,
|
||||
MockBackend,
|
||||
BaseRequestOptions,
|
||||
provide(Http, {
|
||||
{ provide: Http,
|
||||
useFactory: (backend: MockBackend, options: BaseRequestOptions) =>
|
||||
new Http(backend, options),
|
||||
deps: [MockBackend, BaseRequestOptions]
|
||||
})
|
||||
}
|
||||
]);
|
||||
|
||||
beforeEach(inject([MockBackend, Phone],
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// #docregion
|
||||
import { provide } from '@angular/core';
|
||||
import { HTTP_PROVIDERS } from '@angular/http';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
|
@ -35,8 +34,8 @@ class MockPhone extends Phone {
|
|||
describe('PhoneDetailComponent', () => {
|
||||
|
||||
beforeEachProviders(() => [
|
||||
provide(Phone, {useClass: MockPhone}),
|
||||
provide('$routeParams', {useValue: {phoneId: 'xyz'}}),
|
||||
{ provide: Phone, useClass: MockPhone },
|
||||
{ provide: '$routeParams', useValue: {phoneId: 'xyz'}},
|
||||
HTTP_PROVIDERS
|
||||
]);
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// #docregion
|
||||
import { provide } from '@angular/core';
|
||||
import { HTTP_PROVIDERS } from '@angular/http';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import {
|
||||
|
@ -32,7 +31,7 @@ class MockPhone extends Phone {
|
|||
describe('PhoneList', () => {
|
||||
|
||||
beforeEachProviders(() => [
|
||||
provide(Phone, {useClass: MockPhone}),
|
||||
{ provide: Phone, useClass: MockPhone },
|
||||
HTTP_PROVIDERS
|
||||
]);
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { provide } from '@angular/core';
|
||||
import {
|
||||
describe,
|
||||
beforeEach,
|
||||
|
@ -23,15 +22,15 @@ describe('Phone', function() {
|
|||
{name: 'Phone Z', snippet: '', images: []}
|
||||
];
|
||||
let mockBackend:MockBackend;
|
||||
|
||||
|
||||
beforeEachProviders(() => [
|
||||
Phone,
|
||||
MockBackend,
|
||||
BaseRequestOptions,
|
||||
provide(Http, {
|
||||
{ provide: Http,
|
||||
useFactory: (backend: MockBackend, options: BaseRequestOptions) => new Http(backend, options),
|
||||
deps: [MockBackend, BaseRequestOptions]
|
||||
})
|
||||
}
|
||||
]);
|
||||
|
||||
beforeEach(inject([MockBackend, Phone], (_mockBackend_:MockBackend, _phone_:Phone) => {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// #docregion
|
||||
// #docregion imports
|
||||
import { provide } from '@angular/core';
|
||||
import {
|
||||
LocationStrategy,
|
||||
HashLocationStrategy,
|
||||
|
@ -17,8 +16,8 @@ import { AppComponent } from './app.component';
|
|||
bootstrap(AppComponent, [
|
||||
HTTP_PROVIDERS,
|
||||
ROUTER_PROVIDERS,
|
||||
provide(APP_BASE_HREF, {useValue: '!'}),
|
||||
provide(LocationStrategy, {useClass: HashLocationStrategy}),
|
||||
{ provide: APP_BASE_HREF, useValue: '!' },
|
||||
{ provide: LocationStrategy, useClass: HashLocationStrategy },
|
||||
Phone
|
||||
]);
|
||||
// #enddocregion bootstrap
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// #docregion
|
||||
import { provide } from '@angular/core';
|
||||
import { HTTP_PROVIDERS } from '@angular/http';
|
||||
// #docregion routeparams
|
||||
import { RouteParams } from '@angular/router-deprecated';
|
||||
|
@ -41,8 +40,8 @@ describe('PhoneDetailComponent', () => {
|
|||
// #docregion routeparams
|
||||
|
||||
beforeEachProviders(() => [
|
||||
provide(Phone, {useClass: MockPhone}),
|
||||
provide(RouteParams, {useValue: new RouteParams({phoneId: 'xyz'})}),
|
||||
{ provide: Phone, useClass: MockPhone },
|
||||
{ provide: RouteParams, useValue: new RouteParams({phoneId: 'xyz'})},
|
||||
HTTP_PROVIDERS
|
||||
]);
|
||||
// #enddocregion routeparams
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// #docregion routestuff
|
||||
import { provide, ApplicationRef } from '@angular/core';
|
||||
import { ApplicationRef } from '@angular/core';
|
||||
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
|
||||
import { HTTP_PROVIDERS } from '@angular/http';
|
||||
import {
|
||||
|
@ -40,14 +40,14 @@ class MockPhone extends Phone {
|
|||
describe('PhoneList', () => {
|
||||
|
||||
// #docregion routestuff
|
||||
|
||||
|
||||
beforeEachProviders(() => [
|
||||
provide(Phone, {useClass: MockPhone}),
|
||||
{ provide: Phone, useClass: MockPhone},
|
||||
HTTP_PROVIDERS,
|
||||
ROUTER_PROVIDERS,
|
||||
provide(ApplicationRef, {useClass: MockApplicationRef}),
|
||||
provide(ROUTER_PRIMARY_COMPONENT, {useValue: AppComponent}),
|
||||
provide(LocationStrategy, {useClass: MockLocationStrategy}),
|
||||
{ provide: ApplicationRef, useClass: MockApplicationRef },
|
||||
{ provide: ROUTER_PRIMARY_COMPONENT, useValue: AppComponent },
|
||||
{ provide: LocationStrategy, useClass: MockLocationStrategy},
|
||||
]);
|
||||
// #enddocregion routestuff
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ require('zone.js/dist/zone');
|
|||
require('zone.js/dist/long-stack-trace-zone');
|
||||
require('zone.js/dist/jasmine-patch');
|
||||
require('zone.js/dist/async-test');
|
||||
require('zone.js/dist/fake-async-test');
|
||||
|
||||
var appContext = require.context('../src', true, /\.spec\.ts/);
|
||||
|
||||
|
|
|
@ -46,9 +46,6 @@ block real-logger
|
|||
block optional-logger
|
||||
//- TBC.
|
||||
|
||||
block provider-function-etc
|
||||
//- N/A
|
||||
|
||||
block provider-ctor-args
|
||||
- var _secondParam = 'named parameter, such as <code>useClass</code>'
|
||||
:marked
|
||||
|
@ -62,10 +59,8 @@ block dart-diff-const-metadata
|
|||
For that reason, we can't call functions to get values
|
||||
to use within an annotation.
|
||||
Instead, we use constant literals or constant constructors.
|
||||
For example, a TypeScript program might use the
|
||||
function call `provide(Logger, {useClass: BetterLogger})`,
|
||||
which is equivalent to the TypeScript code
|
||||
`new Provider(Logger, {useClass: BetterLogger})`.
|
||||
For example, a TypeScript program will use the
|
||||
object literal `{ provide: Logger, useClass: BetterLogger }`.
|
||||
A Dart annotation would instead use the constant value `const Provider(Logger, useClass: BetterLogger)`.
|
||||
|
||||
block dart-diff-const-metadata-ctor
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,16 +7,16 @@ block includes
|
|||
to our Angular applications directly.
|
||||
|
||||
Angular 2应用使用标准的CSS来设置样式。这意味着我们可以把关于CSS的那些知识和技能直接用于我们的Angular程序中,比如:样式表、选择器、规则,以及媒体查询等。
|
||||
|
||||
|
||||
On top of this, Angular has the ability to bundle *component styles*
|
||||
with our components enabling a more modular design than regular stylesheets.
|
||||
|
||||
在此基础上,Angular还能把*组件样式*紧紧的“捆绑”在我们的组件上,以实现一种比标准样式表更加模块化的设计。
|
||||
|
||||
|
||||
In this chapter we learn how to load and apply these *component styles*.
|
||||
|
||||
在本章中,我们将学到如何加载和使用这些*组件样式*。
|
||||
|
||||
|
||||
# Table Of Contents
|
||||
# 目录
|
||||
|
||||
|
@ -40,11 +40,11 @@ p 运行本章这些代码的#[+liveExampleLink2("在线例子")]
|
|||
:marked
|
||||
## Using Component Styles
|
||||
## 使用组件样式
|
||||
|
||||
|
||||
For every Angular 2 component we write, we may define not only an HTML template,
|
||||
but also the CSS styles that go with that template,
|
||||
specifying any selectors, rules, and media queries that we need.
|
||||
|
||||
|
||||
对于我们写的每个Angular 2组件来说,除了定义HTML模板之外,我们还要用于模板的CSS样式、
|
||||
指定需要的选择器、规则和媒体查询。
|
||||
|
||||
|
@ -55,14 +55,14 @@ p 运行本章这些代码的#[+liveExampleLink2("在线例子")]
|
|||
它的实现方式之一,是在组件的元数据中设置`styles`属性。
|
||||
`styles`属性可以接受一个包含CSS代码的字符串数组。
|
||||
通常我们只给它一个字符串就行了,如同下例:
|
||||
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-app.component.ts')(format='.')
|
||||
|
||||
:marked
|
||||
Component styles differ from traditional, global styles in a couple of ways.
|
||||
|
||||
组件样式在很多方面都不同于传统的全局性样式。
|
||||
|
||||
|
||||
Firstly, the selectors we put into a component's styles *only apply within the template
|
||||
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
|
||||
|
@ -70,32 +70,32 @@ p 运行本章这些代码的#[+liveExampleLink2("在线例子")]
|
|||
|
||||
首先,我们放在组件样式中的选择器,只会应用在组件自身的模板中。上面这个例子中的`h1`选择器只会对
|
||||
`HeroAppComponent`模板中的`<h1>`标签生效,而对应用中其它地方的`<h1>`元素毫无影响。
|
||||
|
||||
|
||||
This is a big improvement in modularity compared to how CSS traditionally works:
|
||||
|
||||
这种模块化相对于CSS的传统工作方式是一个巨大的改进:
|
||||
|
||||
1. We can use the CSS class names and selectors that make the most sense in the context of each component.
|
||||
|
||||
|
||||
1. We can use the CSS class names and selectors that make the most sense in the context of each component.
|
||||
|
||||
1. 只有在每个组件的情境中使用CSS类名和选择器,才是最有意义的。
|
||||
|
||||
|
||||
1. Class names and selectors are local to the component and won't collide with
|
||||
classes and selectors used elsewhere in the application.
|
||||
|
||||
|
||||
1. 类名和选择器是仅属于组件内部的,它不会和应用中其它地方的类名和选择器出现冲突。
|
||||
|
||||
|
||||
1. Our component's styles *cannot* be changed by changes to styles elsewhere in the application.
|
||||
|
||||
|
||||
1. 我们组件的样式*不会*因为别的地方修改了样式而被意外改变。
|
||||
|
||||
|
||||
1. We can co-locate the CSS code of each component with the TypeScript and HTML code of the component,
|
||||
which leads to a neat and tidy project structure.
|
||||
|
||||
1. 我们可以让每个组件的CSS代码和它的TypeScript代码、HTML代码放在一起,这将促成清爽整洁的项目结构。
|
||||
|
||||
|
||||
1. We can change or remove component CSS code in the future without trawling through the
|
||||
whole application to see where else it may have been used. We just look at the component we're in.
|
||||
|
||||
|
||||
1. 将来我们可以修改或移除组件的CSS代码,而不用遍历整个应用来看它有没有被别处用到,只要看看当前组件就可以了。
|
||||
|
||||
a(id="special-selectors")
|
||||
|
@ -103,12 +103,12 @@ a(id="special-selectors")
|
|||
:marked
|
||||
## Special selectors
|
||||
## 特殊的选择器
|
||||
|
||||
|
||||
Component styles have a few special *selectors* from the world of
|
||||
[shadow DOM style scoping](https://www.w3.org/TR/css-scoping-1):
|
||||
|
||||
“组件样式”中有一些特殊的*选择器*,它们是从[局限化CSS](https://www.w3.org/TR/css-scoping-1)的世界里引入的Shadow DOM(影子DOM)选择器。
|
||||
|
||||
|
||||
### :host
|
||||
### :host
|
||||
|
||||
|
@ -116,7 +116,7 @@ a(id="special-selectors")
|
|||
targeting elements *inside* the component's template):
|
||||
|
||||
使用`:host`伪类选择器,用来选择组件*宿主*元素中的元素(相对于组件模板*内部*的元素)。
|
||||
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-details.component.css', 'host')(format='.')
|
||||
|
||||
:marked
|
||||
|
@ -125,66 +125,66 @@ a(id="special-selectors")
|
|||
component's own template. It is in a parent component's template.
|
||||
|
||||
这是我们能以宿主元素为目标的*唯一*方式。除此之外,我们将没办法指定它,因为宿主不是组件自身模板的一部分,而是父组件模板的一部分。
|
||||
|
||||
Use the *function form* to apply host styles conditionally by
|
||||
|
||||
Use the *function form* to apply host styles conditionally by
|
||||
including another selector inside parentheses after `:host`.
|
||||
|
||||
要把宿主样式作为条件,就要像*函数*一样把其它选择器放在`:host`后面的括号中。
|
||||
|
||||
|
||||
In the next example we target the host element again, but only when it also has the `active` CSS class.
|
||||
|
||||
在下一个例子中,我们又一次把宿主元素作为目标,但是只有当它同时带有`active` CSS类的时候才会生效。
|
||||
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-details.component.css', 'hostfunction')(format=".")
|
||||
|
||||
:marked
|
||||
### :host-context
|
||||
### :host-context
|
||||
|
||||
|
||||
Sometimes it is useful to apply styles based on some condition *outside* a component's view.
|
||||
For example, there may be a CSS theme class applied to the document `<body>` element, and
|
||||
we want to change how our component looks based on that.
|
||||
|
||||
有时候,基于某些来自组件视图*外部*的条件应用样式是很有用的。
|
||||
比如,在文档的`<body>`元素上可能有一个用于表示样式主题(Theme)的CSS类,而我们应当基于它来决定组件的样式。
|
||||
|
||||
|
||||
Use the `:host-context()` pseudo-class selector. It works just like the function
|
||||
form of `:host()`. It looks for a CSS class in *any ancestor* of the component host element, all the way
|
||||
up to the document root. It's useful when combined with another selector.
|
||||
|
||||
这时可以使用`:host-context()`伪类选择器。它也以类似`:host()`形式使用。它在当前组件宿主元素的*祖先节点*中查找CSS类,
|
||||
直到文档的根节点为止。在与其它选择器组合使用时,它非常有用。
|
||||
|
||||
|
||||
In the following example, we apply a `background-color` style to all `<h2>` elements *inside* the component, only
|
||||
if some ancestor element has the CSS class `theme-light`.
|
||||
|
||||
在下面的例子中,只有当某个祖先元素有CSS类`theme-light`时,我们才会把`background-color`样式应用到组件*内部*的所有`<h2>`元素中。
|
||||
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-details.component.css', 'hostcontext')(format='.')
|
||||
|
||||
:marked
|
||||
### /deep/
|
||||
### /deep/
|
||||
|
||||
|
||||
Component styles normally apply only to the HTML in the component's own template.
|
||||
|
||||
“组件样式”通常只会作用于组件自身的HTML上。
|
||||
|
||||
|
||||
We can use the `/deep/` selector to force a style down through the child component tree into all the child component views.
|
||||
The `/deep/` selector works to any depth of nested components, and it applies *both to the view
|
||||
children and the content children* of the component.
|
||||
|
||||
我们可以使用`/deep/`选择器,来强制一个样式对各级子组件的视图也生效,它*不但作用于组件的子视图,也会作用于组件的内容*。
|
||||
|
||||
In this example, we target all `<h3>` elements, from the host element down
|
||||
|
||||
In this example, we target all `<h3>` elements, from the host element down
|
||||
through this component to all of its child elements in the DOM:
|
||||
|
||||
|
||||
在这个例子中,我们以所有的`<h3>`元素为目标,从宿主元素到当前元素再到DOM中的所有子元素:
|
||||
+makeExample('component-styles/ts/app/hero-details.component.css', 'deep')(format=".")
|
||||
|
||||
:marked
|
||||
The `/deep/` selector also has the alias `>>>`. We can use either of the two interchangeably.
|
||||
|
||||
|
||||
`/deep/`选择器还有一个别名`>>>`。我们可以任意交替使用它们。
|
||||
|
||||
.alert.is-important
|
||||
|
@ -193,7 +193,7 @@ a(id="special-selectors")
|
|||
This is the default and it is what we use most of the time. See the
|
||||
[Controlling View Encapsulation](#view-encapsulation)
|
||||
section for more details.
|
||||
|
||||
|
||||
`/deep/`和`>>>`选择器只能被用在**仿真(Emulated)**模式下。
|
||||
这种方式是默认值,也是用得最多的方式。要了解更多,请参阅[控制视图包装模式](#view-encapsulation)一节。
|
||||
|
||||
|
@ -202,9 +202,9 @@ a(id='loading-styles')
|
|||
:marked
|
||||
## Loading Styles into Components
|
||||
## 把样式加载进组件中
|
||||
|
||||
|
||||
We have several ways to add styles to a component:
|
||||
|
||||
|
||||
我们有几种方式来把样式加入组件:
|
||||
* inline in the template HTML
|
||||
* 内联在模板的HTML中
|
||||
|
@ -212,42 +212,42 @@ a(id='loading-styles')
|
|||
* 设置`styles`或`styleUrls`元数据
|
||||
* with CSS imports
|
||||
* 通过CSS文件导入
|
||||
|
||||
|
||||
The scoping rules outlined above apply to each of these loading patterns.
|
||||
|
||||
上述局限化规则对所有这些加载模式都适用。
|
||||
|
||||
|
||||
### 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.
|
||||
|
||||
我们可以给`@Component`#{_decoratorCn}添加一个`styles`数组型属性。
|
||||
这个数组中的每一个字符串(通常也只有一个)定义一份CSS。
|
||||
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-app.component.ts')
|
||||
|
||||
:marked
|
||||
### Template Inline Styles
|
||||
### 模板内联样式
|
||||
|
||||
|
||||
We can embed styles directly into the HTML template by putting them
|
||||
inside `<style>` tags.
|
||||
|
||||
我们也可以把它们放到`<style>`标签中来直接在HTML模板中嵌入样式。
|
||||
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-controls.component.ts', 'inlinestyles')
|
||||
|
||||
:marked
|
||||
### Style URLs in Metadata
|
||||
### 元数据中的样式表URL
|
||||
|
||||
|
||||
We can load styles from external CSS files by adding a `styleUrls` attribute
|
||||
into a component's `@Component` #{_decorator}:
|
||||
|
||||
|
||||
我们还可以通过给组件的`@Component`#{_decoratorCn}中添加一个`styleUrls`属性来从外部CSS文件中加载样式:
|
||||
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-details.component.ts', 'styleurls')
|
||||
|
||||
block style-url
|
||||
|
@ -259,7 +259,7 @@ block style-url
|
|||
That's why the example URL begins `app/`.
|
||||
See [Appendix 2](#relative-urls) to specify a URL relative to the
|
||||
component file.
|
||||
|
||||
|
||||
URL是***相对于应用程序根目录的***,它通常是应用的宿主页面`index.html`所在的地方。
|
||||
这个样式文件的URL*不是*相对于组件文件的。这就是为什么范例中的URL用`app/`开头儿。
|
||||
参见[附录2](#relative-urls)来了解如何指定相对于组件文件的URL。
|
||||
|
@ -269,11 +269,11 @@ block module-bundlers
|
|||
: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:
|
||||
|
||||
|
||||
像Webpack这类模块打包器的用户可能会使用`styles`属性来在构建时从外部文件中加载样式。他们可能这样写:
|
||||
|
||||
`styles: [require('my.component.css')]`
|
||||
|
||||
|
||||
`styles: [require('my.component.css')]`
|
||||
|
||||
We set the `styles` property, **not** `styleUrls` property! The module
|
||||
|
@ -282,43 +282,43 @@ block module-bundlers
|
|||
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.
|
||||
|
||||
|
||||
注意,这时候我们是在设置`styles`属性,**而不是**`styleUrls`属性!
|
||||
是模块打包器在加载CSS字符串,而不是Angular。
|
||||
Angular看到的只是打包器加载它们之后的CSS字符串。
|
||||
对Angular来说,这跟我们手写了`styles`数组没有任何区别。
|
||||
要了解这种CSS加载方式的更多信息,请参阅相应模块打包器的文档。
|
||||
|
||||
|
||||
:marked
|
||||
### Template Link Tags
|
||||
### 模板中的link标签
|
||||
|
||||
|
||||
We can also embed `<link>` tags into the component's HTML template.
|
||||
|
||||
我们也可以在组件的HTML模板中嵌入`<link>`标签。
|
||||
|
||||
As with `styleUrls`, the link tag's `href` URL is relative to the
|
||||
|
||||
As with `styleUrls`, the link tag's `href` URL is relative to the
|
||||
application root, not relative to the component file.
|
||||
|
||||
像`styleUrls`标签一样,这个link标签的`href`指向的URL也是相对于应用的根目录的,而不是组件文件。
|
||||
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-team.component.ts', 'stylelink')
|
||||
|
||||
:marked
|
||||
### CSS @imports
|
||||
### CSS @imports
|
||||
|
||||
|
||||
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).
|
||||
|
||||
我们还可以利用标准的CSS[`@import`规则](https://developer.mozilla.org/en/docs/Web/CSS/@import)来把其它CSS文件导入到我们的CSS文件中。
|
||||
|
||||
|
||||
block css-import-url
|
||||
:marked
|
||||
In *this* case the URL is relative to the CSS file into which we are importing.
|
||||
|
||||
|
||||
在*这种*情况下,URL是相对于我们执行导入操作的CSS文件的。
|
||||
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-details.component.css', 'import', 'app/hero-details.component.css (excerpt)')
|
||||
|
||||
a#view-encapsulation
|
||||
|
@ -326,44 +326,44 @@ a#view-encapsulation
|
|||
:marked
|
||||
## Controlling View Encapsulation: Native, Emulated, and None
|
||||
## 控制视图的包装模式:原生(Native),仿真(Emulated)和无(None)
|
||||
|
||||
|
||||
As discussed above, component CSS styles are *encapsulated* into the component's own view and do
|
||||
not affect the rest of the application.
|
||||
|
||||
像上面讨论过的一样,组件的CSS样式被包装进了自己的视图中,而不会影响到应用程序的其它部分。
|
||||
|
||||
|
||||
We can control how this encapsulation happens on a *per
|
||||
component* basis by setting the *view encapsulation mode* in the component metadata. There
|
||||
are three modes to choose from:
|
||||
|
||||
通过在组件的元数据上设置*视图包装模式*,我们可以分别控制*每个组件*的包装模式。
|
||||
可选的包装模式一共有三种:
|
||||
|
||||
|
||||
* `Native` view encapsulation uses the browser's native [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM)
|
||||
implementation to attach a Shadow DOM to the component's host element, and then puts the component
|
||||
view inside that Shadow DOM. The component's styles are included within the Shadow DOM.
|
||||
* `Native`模式使用浏览器原生的[Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM)
|
||||
实现来为组件的宿主元素附加一个Shadow DOM。组件的样式被包裹在这个Shadow DOM中。(译注:不进不出,没有样式能进来,组件样式出不去。)
|
||||
|
||||
|
||||
* `Emulated` view encapsulation (**the default**) emulates the behavior of Shadow DOM by preprocessing
|
||||
(and renaming) the CSS code to effectively scope the CSS to the component's view.
|
||||
See [Appendix 1](#inspect-generated-css) for details.
|
||||
|
||||
* `Emulated`模式(**默认值**)通过预处理(并改名)CSS代码来仿真Shadow DOM的行为,以达到把CSS样式局限在组件视图中的目的。
|
||||
参见[附录1](#inspect-generated-css)了解详情。(译注:只进不出,全局样式能进来,组件样式出不去)
|
||||
|
||||
* `None` means that Angular does no view encapsulation.
|
||||
|
||||
* `None` means that Angular does no view encapsulation.
|
||||
Angular adds the CSS to the global styles.
|
||||
The scoping rules, isolations, and protections discussed earlier do not apply.
|
||||
This is essentially the same as pasting the component's styles into the HTML.
|
||||
* `None`意味着Angular不使用视图包装。
|
||||
Angular会把CSS添加到全局样式中。而不会应用上前面讨论过的那些局限化规则、隔离和保护等规则。
|
||||
从本质上来说,这跟把组件的样式直接放进HTML是一样的。(译注:能进能出。)
|
||||
|
||||
|
||||
Set the components encapsulation mode using the `encapsulation` property in the component metadata:
|
||||
|
||||
通过组件元数据中的`encapsulation`属性来设置组件包装模式:
|
||||
|
||||
|
||||
+makeExample('component-styles/ts/app/quest-summary.component.ts', 'encapsulation.native')(format='.')
|
||||
|
||||
:marked
|
||||
|
@ -371,7 +371,7 @@ a#view-encapsulation
|
|||
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.
|
||||
|
||||
|
||||
原生(`Native`)模式只适用于[有原生Shadow DOM支持的浏览器](http://caniuse.com/#feat=shadowdom)。
|
||||
因此仍然受到很多限制,这就是为什么我们会把仿真(`Emulated`)模式作为默认选项,并建议将其用于大多数情况。
|
||||
|
||||
|
@ -380,18 +380,18 @@ a#inspect-generated-css
|
|||
:marked
|
||||
## Appendix 1: Inspecting The CSS Generated in Emulated View Encapsulation
|
||||
## 附录1:查看仿真(Emulated)模式下生成的CSS
|
||||
|
||||
|
||||
When using the default emulated view encapsulation, Angular preprocesses
|
||||
all component styles so that they approximate the standard Shadow CSS scoping rules.
|
||||
|
||||
当使用默认的“仿真”模式时,Angular会对组件的所有样式进行预处理,让它们模仿出标准的Shadow CSS局限化规则。
|
||||
|
||||
|
||||
When we inspect the DOM of a running Angular application with emulated view
|
||||
encapsulation enabled, we see that each DOM element has some extra attributes
|
||||
attached to it:
|
||||
|
||||
当我们查看启用了“仿真”模式的Angular应用时,我们看到每个DOM元素都被加上了一些额外的属性。
|
||||
|
||||
|
||||
code-example(format="").
|
||||
<hero-details _nghost-pmm-5>
|
||||
<h2 _ngcontent-pmm-5>Mister Fantastic</h2>
|
||||
|
@ -402,26 +402,26 @@ code-example(format="").
|
|||
|
||||
:marked
|
||||
We see two kinds of generated attributes:
|
||||
|
||||
|
||||
我们看到了两种被生成的属性:
|
||||
* An element that would be a Shadow DOM host in native encapsulation has a
|
||||
generated `_nghost` attribute. This is typically the case for component host elements.
|
||||
|
||||
* 一个元素在原生包装方式下可能是Shadow DOM的宿主,在这里被自动添加上一个`_nghost`属性。
|
||||
这是组件宿主元素的典型情况。
|
||||
|
||||
* An element within a component's view has a `_ngcontent` attribute
|
||||
|
||||
* An element within a component's view has a `_ngcontent` attribute
|
||||
that identifies to which host's emulated Shadow DOM this element belongs.
|
||||
|
||||
* 组件视图中的每一个元素,都有一个`_ngcontent`属性,它会标记出该元素是哪个宿主的模拟Shadow DOM。
|
||||
|
||||
|
||||
The exact values of these attributes are not important. They are automatically
|
||||
generated and we never refer to them in application code. But they are targeted
|
||||
by the generated component styles, which we'll find in the `<head>` section of the DOM:
|
||||
|
||||
这些属性的具体值并不重要。它们是自动生成的,并且我们永远不会在程序代码中直接引用到它们。
|
||||
但它们会作为生成的组件样式的目标,就像我们在DOM的`<head>`区所看到的:
|
||||
|
||||
|
||||
code-example(format="").
|
||||
[_nghost-pmm-5] {
|
||||
display: block;
|
||||
|
@ -440,21 +440,21 @@ code-example(format="").
|
|||
|
||||
这些就是我们写的那些样式被处理后的结果,于是每个选择器都被增加了`_nghost`或`_ngcontent`属性选择器。
|
||||
在这些附加选择器的帮助下,我们实现了本指南中所描述的这些局限化规则。
|
||||
|
||||
|
||||
We'll likely live with *emulated* mode until shadow DOM gains traction.
|
||||
|
||||
小伙伴儿们会很愉快的使用*仿真*模式 —— 直到有一天Shadow DOM获得全面支持。
|
||||
|
||||
|
||||
a#relative-urls
|
||||
.l-main-section
|
||||
:marked
|
||||
## Appendix 2: Loading Styles with Relative URLs
|
||||
## 附录2:使用相对URL加载样式
|
||||
|
||||
|
||||
It's common practice to split a component's code, HTML, and CSS into three separate files in the same directory:
|
||||
|
||||
把组件的代码(ts/js)、HTML和CSS分别放到同一个目录下的三个不同文件,是一个常用的实践:
|
||||
|
||||
|
||||
code-example(format='').
|
||||
quest-summary.component.ts
|
||||
quest-summary.component.html
|
||||
|
@ -464,18 +464,18 @@ code-example(format='').
|
|||
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.
|
||||
|
||||
|
||||
我们会通过设置元数据的`templateUrl`和`styleUrls`属性把模板和CSS文件包含进来。
|
||||
既然这些文件都与组件(代码)文件放在一起,那么通过名字,而不是到应用程序根目录的全路径来指定它,就会是一个漂亮的方式。
|
||||
|
||||
block module-id
|
||||
:marked
|
||||
We can change the way Angular calculates the full URL be setting the component metadata's `moduleId` property to `module.id`.
|
||||
|
||||
|
||||
通过把组件元数据的`moduleId`属性设置为`module.id`,我们可以更改Angular计算完整URL的方式
|
||||
|
||||
+makeExample('component-styles/ts/app/quest-summary.component.ts','', 'app/quest-summary.component.ts')
|
||||
:marked
|
||||
Learn more about `moduleId` in the [Component-Relative Paths](../cookbook/component-relative-paths.html) chapter.
|
||||
|
||||
|
||||
要学习更多关于`moduleId`的知识,请参见[相对于组件的路径](../cookbook/component-relative-paths.html)一章。
|
||||
|
|
|
@ -754,7 +754,7 @@ code-example(format="nocode").
|
|||
最重要的是:当注入器需要一个`Logger`时,它得先有一个供应商。
|
||||
|
||||
//- Dart limitation: the provide function isn't const so it cannot be used in an annotation.
|
||||
- var __andProvideFn = _docsFor == 'dart' ? '' : 'and <i>provide</i> function';
|
||||
- var __andProvideFn = _docsFor == 'dart' ? '' : 'and <i>provide</i> object literal';
|
||||
#provide
|
||||
:marked
|
||||
### The *Provider* class !{__andProvideFn}
|
||||
|
@ -765,41 +765,12 @@ code-example(format="nocode").
|
|||
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-1')
|
||||
|
||||
:marked
|
||||
This is actually a short-hand expression for a provider registration that creates a new instance of the
|
||||
[Provider](../api/core/Provider-class.html) class.
|
||||
This is actually a short-hand expression for a provider registration using the _provider_ object literal.
|
||||
|
||||
这实际上是供应商注册的一个简写形式,它会创建[Provider](../api/core/Provider-class.html)类的一个新实例。
|
||||
|
||||
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-2')
|
||||
|
||||
block provider-function-etc
|
||||
:marked
|
||||
The [provide](../api/core/provide-function.html) function is the typical way
|
||||
to create a `Provider`:
|
||||
|
||||
[provide](../api/core/provide-function.html)函数是典型的用来创建`Provider`的方法:
|
||||
|
||||
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-3')
|
||||
|
||||
:marked
|
||||
Or we can declare a provider in an _object literal_ and skip the `provide` function.
|
||||
|
||||
或者我们可以在一个_对象文本_声明一个提供商,并忽略`provide`函数。
|
||||
|
||||
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-3a')
|
||||
|
||||
:marked
|
||||
Pick the syntax that you prefer. They all do the same thing.
|
||||
|
||||
挑选一种你自己喜欢的语法。它们都能做同样的事。
|
||||
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-3a')
|
||||
|
||||
block provider-ctor-args
|
||||
- var _secondParam = 'provider definition object';
|
||||
:marked
|
||||
In each syntax, we supply two types of values.
|
||||
|
||||
在每种语法中,我们提供了两个类型的值。
|
||||
|
||||
//- var _secondParam = _docsFor == 'dart' ? 'named parameter, such as <code>useClass</code>' : 'provider definition object';
|
||||
:marked
|
||||
The first is the [token](#token) that serves as the key for both locating a dependency value
|
||||
|
|
|
@ -351,7 +351,7 @@ figure.image-display
|
|||
Providing the router providers at the root makes the Component Router available everywhere in our application.
|
||||
.l-sub-section
|
||||
:marked
|
||||
Learn about providers, the `provide` function, and injected services in the
|
||||
Learn about providers, the `provide` object literal, and injected services in the
|
||||
[Dependency Injection chapter](dependency-injection.html).
|
||||
:marked
|
||||
### The *AppComponent* shell
|
||||
|
@ -1472,8 +1472,7 @@ code-example(format=".", language="bash").
|
|||
We can go old-school with the `HashLocationStrategy` by
|
||||
providing it as the router's `LocationStrategy` during application bootstrapping.
|
||||
|
||||
First, import the `provide` symbol for Dependency Injection and the
|
||||
`Location` and `HashLocationStrategy` symbols from the router.
|
||||
Import the `LocationStrategy` and `HashLocationStrategy` symbols from `@angular/common`.
|
||||
|
||||
Then *override* the default strategy defined in `ROUTE_PROVIDERS` by
|
||||
providing the `HashLocationStrategy` later in the `bootstrap` providers array argument:
|
||||
|
|
|
@ -1007,7 +1007,7 @@ a(href="#toc") 回到顶部
|
|||
|
||||
**坚持**使用大写驼峰命名法来命名接口。
|
||||
|
||||
.s-rule.do
|
||||
.s-rule.consider
|
||||
:marked
|
||||
**Consider** naming an interface without an `I` prefix.
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ include ../_util-fns
|
|||
up with a project structure with a large number of relatively small files. This is
|
||||
a much neater way to organize things than a small number of large files, but it
|
||||
doesn't work that well if you have to load all those files to the HTML page with
|
||||
`<script>` tags. Especially when you also have to maintain those tags in the correct
|
||||
<script> tags. Especially when you also have to maintain those tags in the correct
|
||||
order. That's why it's a good idea to start using a *module loader*.
|
||||
|
||||
当我们把应用代码分解成每个文件中放一个组件之后,我们通常会得到一个由大量相对较小的文件组成的项目结构。
|
||||
|
@ -1775,7 +1775,7 @@ code-example(format="").
|
|||
2. 注册了一个名叫`phone`的**Angular 1工厂**,它是一个`Phones`服务的*降级*版。
|
||||
|
||||
Now that we are loading `phone.service.ts` through an import that is resolved
|
||||
by SystemJS, we should **remove the `<script>` tag** for the service from `index.html`.
|
||||
by SystemJS, we should **remove the <script> tag** for the service from `index.html`.
|
||||
This is something we'll do to all our components as we upgrade them. Simultaneously
|
||||
with the Angular 1 to 2 upgrade we're also migrating our code from scripts to modules.
|
||||
|
||||
|
@ -1893,7 +1893,7 @@ code-example(format="").
|
|||
这里的`<angular.IDirectiveFactory>`类型注解是为了让TypeScript编译器知道这个
|
||||
降级方法(`downgradeNg2Component`)的返回值能作为指令工厂使用。
|
||||
|
||||
At this point, also remove the `<script>` tag for the phone list component from `index.html`.
|
||||
At this point, also remove the <script> tag for the phone list component from `index.html`.
|
||||
|
||||
这时,也从`index.html`中移除电话列表组件的`<script>`标签。
|
||||
|
||||
|
@ -1993,7 +1993,7 @@ code-example(format="").
|
|||
+makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'phone-detail', 'app/main.ts')
|
||||
|
||||
:marked
|
||||
We should now also remove the phone detail component `<script>` tag from `index.html`.
|
||||
We should now also remove the phone detail component <script> tag from `index.html`.
|
||||
|
||||
在`app.module.ts`中的路由器配置中,我们同样把详情路由改成实例化一个组件:
|
||||
|
||||
|
@ -2016,7 +2016,7 @@ code-example(format="").
|
|||
|
||||
:marked
|
||||
In the component we should now import and declare our newly created pipe (as well as
|
||||
remove the filter `<script>` tag from `index.html`):
|
||||
remove the filter <script> tag from `index.html`):
|
||||
|
||||
当我们做这个修改时,也要同时从`core`模块文件中移除对该过滤器的注册。该模块的内容变成了:
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ code-example(format="." language="bash").
|
|||
In this demo service we log the error to the console; we should do better in real life.
|
||||
|
||||
We've also decided to return a user friendly form of the error to
|
||||
to the caller in a rejected promise so that the caller can display a proper error message to the user.
|
||||
the caller in a rejected promise so that the caller can display a proper error message to the user.
|
||||
|
||||
### Promises are Promises
|
||||
Although we made significant *internal* changes to `getHeroes()`, the public signature did not change.
|
||||
|
@ -235,7 +235,7 @@ code-example(format="." language="bash").
|
|||
:marked
|
||||
The same save method is used for both add and edit since `HeroService` will know when to call `post` vs `put` based on the state of the `Hero` object.
|
||||
|
||||
After we save a hero, we redirect the browser back to the to the previous page using the `goBack()` method.
|
||||
After we save a hero, we redirect the browser back to the previous page using the `goBack()` method.
|
||||
|
||||
+makeExample('toh-6/ts/app/hero-detail.component.ts', 'goback', 'app/hero-detail.component.ts (goBack)')(format=".")
|
||||
|
||||
|
|
Loading…
Reference in New Issue