docs(dependency-injection): add Dart sample

closes #817
This commit is contained in:
luis 2016-02-06 17:02:44 -05:00 committed by Kathy Walrath
parent ee5a4e131a
commit 1ac9316171
32 changed files with 1119 additions and 3 deletions

3
.gitignore vendored
View File

@ -3,13 +3,14 @@ _temp
bower_components
jspm_packages
typings
packages
**/packages
build
pubspec.lock
.pub
.packages
*.map
.DS_Store
**/*.iml
.idea
**/js/latest/api
**/ts/latest/api

View File

@ -0,0 +1,63 @@
// #docplaster
// #docregion
// #docregion imports
import 'package:angular2/core.dart';
import 'car/car_component.dart';
import 'heroes/heroes_component.dart';
import 'app_config.dart';
import 'logger_service.dart';
import 'user_service.dart';
// #enddocregion imports
import 'injector_component.dart';
import 'providers_component.dart';
@Component(
selector: 'my-app',
template: '''
<h1>{{title}}</h1>
<my-car></my-car>
<my-injectors></my-injectors>
<my-tests></my-tests>
<h2>User</h2>
<p id="user">
{{userInfo}}
<button (click)=\'nextUser()\'>Next User</button>
<p>
<my-heroes id="authorized" *ngIf="isAuthorized"></my-heroes>
<my-heroes id="unauthorized" *ngIf="!isAuthorized"></my-heroes>
''',
directives: const [CarComponent, HeroesComponent, InjectorComponent, ProvidersComponent],
// #docregion providers
providers: const [Logger, UserService, const Provider(Config, useValue: CONFIG)]
// #enddocregion providers
)
class AppComponent {
UserService _userService;
String title;
//#docregion ctor
AppComponent(Config config, this._userService) {
title = config.title;
}
// #enddocregion ctor
bool get isAuthorized {
return user.isAuthorized;
}
void nextUser() {
_userService.getNewUser();
}
User get user {
return _userService.user;
}
String get userInfo {
return 'Current user, ${user.name}, is ${isAuthorized ? "" : "not"} authorized. ';
}
}
// #enddocregion

View File

@ -0,0 +1,28 @@
// Early versions
// #docregion
import 'package:angular2/core.dart';
import 'car/car_component.dart';
import 'heroes/heroes_component_1.dart';
@Component(
selector: 'my-app',
template: '''
<h1>{{title}}</h1>
<my-car></my-car>
<my-heroes></my-heroes>
''',
directives: const [CarComponent, HeroesComponent])
class AppComponent {
var title = 'Dependency Injection';
}
// #enddocregion
/*
//#docregion ctor-di-fail
// FAIL! Injectable `config` is not a class!
AppComponent(HeroService heroService, Map config) {
title = config['title'];
}
//#enddocregion ctor-di-fail
*/

View File

@ -0,0 +1,35 @@
// #docregion
// #docregion imports
import 'package:angular2/core.dart';
import 'car/car_component.dart';
import 'heroes/heroes_component_1.dart';
import 'app_config.dart';
import 'logger_service.dart';
// #enddocregion imports
@Component(
selector: 'my-app',
template: '''
<h1>{{title}}</h1>
<my-car></my-car>
<my-heroes></my-heroes>
''',
directives: const [
CarComponent,
HeroesComponent
],
providers: const [
Logger,
// #docregion provider-config
const Provider('app.config', useValue: CONFIG)
])
class AppComponent {
String title;
// #docregion ctor
AppComponent(@Inject('app.config') Config config) {
title = config.title;
}
}
// #enddocregion

View File

@ -0,0 +1,29 @@
//#docregion
// #docregion token
import 'package:angular2/core.dart';
const APP_CONFIG = const OpaqueToken('app.config');
// #enddocregion token
//#docregion config
abstract class Config {
final String apiEndpoint;
final String title;
const Config({this.apiEndpoint, this.title});
}
class ConfigImpl implements Config {
final String apiEndpoint;
final String title;
const ConfigImpl({this.apiEndpoint, this.title});
}
const CONFIG = const ConfigImpl(apiEndpoint: 'api.heroes.com', title: 'Dependency Injection');
//#enddocregion config
//#docregion config-hash
const CONFIG_HASH = const {'apiEndpoint': 'api.heroes.com', 'title': 'Dependency Injection'};
//#enddocregion config-hash

View File

@ -0,0 +1,32 @@
// #docregion
import 'package:angular2/core.dart';
// #docregion engine
class Engine {
int cylinders = 4;
}
// #enddocregion engine
// #docregion tires
class Tires {
String make = 'Flintstone';
String model = 'Square';
}
// #enddocregion tires
@Injectable()
class Car {
//#docregion car-ctor
Engine engine;
Tires tires;
String description = 'DI';
Car(this.engine, this.tires);
// #enddocregion car-ctor
// Method using the engine and tires
String drive() => '$description car with ${engine.cylinders} cylinders and ${tires.make} tires.';
}
// #enddocregion car

View File

@ -0,0 +1,33 @@
// #docregion
import 'package:angular2/core.dart';
import 'car.dart';
import 'car_no_di.dart' as carNoDi;
import 'car_factory.dart';
import 'car_creations.dart' as carCreations;
import 'car_injector.dart';
@Component(
selector: 'my-car',
template: '''
<h2>Cars</h2>
<div id="di">{{car.drive()}}</div>
<div id="nodi">{{noDiCar.drive()}}</div>
<div id="injector">{{injectorCar.drive()}}</div>
<div id="factory">{{factoryCar.drive()}}</div>
<div id="simple">{{simpleCar.drive()}}</div>
<div id="super">{{superCar.drive()}}</div>
<div id="test">{{testCar.drive()}}</div>
''',
providers: const [Car, Engine, Tires])
class CarComponent {
Car car;
CarComponent(this.car) {}
Car factoryCar = (new CarFactory()).createCar();
Car injectorCar = useInjector();
carNoDi.Car noDiCar = new carNoDi.Car();
Car simpleCar = carCreations.simpleCar();
Car superCar = carCreations.superCar();
Car testCar = carCreations.testCar();
}

View File

@ -0,0 +1,56 @@
// Examples with car and engine variations
// #docplaster
import 'car.dart';
///////// example 1 ////////////
Car simpleCar() {
//#docregion car-ctor-instantiation
// Simple car with 4 cylinders and Flintstone tires.
var car = new Car(new Engine(), new Tires());
//#enddocregion car-ctor-instantiation
car.description = 'Simple';
return car;
}
///////// example 2 ////////////
//#docregion car-ctor-instantiation-with-param
class Engine2 implements Engine {
int cylinders;
Engine2(this.cylinders);
}
//#enddocregion car-ctor-instantiation-with-param
Car superCar() {
//#docregion car-ctor-instantiation-with-param
// Super car with 12 cylinders and Flintstone tires.
var bigCylinders = 12;
var car = new Car(new Engine2(bigCylinders), new Tires());
//#enddocregion car-ctor-instantiation-with-param
car.description = 'Super';
return car;
}
/////////// example 3 //////////
//#docregion car-ctor-instantiation-with-mocks
class MockEngine extends Engine {
int cylinders = 8;
}
class MockTires extends Tires {
String make = 'YokoGoodStone';
}
//#enddocregion car-ctor-instantiation-with-mocks
Car testCar() {
//#docregion car-ctor-instantiation-with-mocks
// Test car with 8 cylinders and YokoGoodStone tires.
var car = new Car(new MockEngine(), new MockTires());
//#enddocregion car-ctor-instantiation-with-mocks
car.description = 'Test';
return car;
}

View File

@ -0,0 +1,15 @@
// #docregion
import 'car.dart';
class CarFactory {
Car createCar() {
var car = new Car(createEngine(), createTires());
car.description = 'Factory';
return car;
}
Engine createEngine() => new Engine();
Tires createTires() => new Tires();
}

View File

@ -0,0 +1,36 @@
// #docplaster
//#docregion
import 'package:angular2/core.dart';
import 'car.dart';
import '../logger_service.dart';
//#docregion injector
Car useInjector() {
Injector injector;
//#enddocregion injector
/*
//#docregion injector-no-new
// Cannot 'new' an Injector like this!
var injector = new Injector([Car, Engine, Tires, Logger]);
//#enddocregion injector-no-new
*/
//#docregion injector
//#docregion injector-create-and-call
injector = Injector.resolveAndCreate([Car, Engine, Tires, Logger]);
//#docregion injector-call
var car = injector.get(Car);
//#enddocregion injector-call
//#enddocregion injector-create-and-call
car.description = 'Injector';
var logger = injector.get(Logger);
logger.log('Injector car.drive() said: ' + car.drive());
return car;
}
//#enddocregion injector
//#enddocregion

View File

@ -0,0 +1,22 @@
// Car without DI
import 'car.dart';
//#docregion car
class Car {
//#docregion car-ctor
Engine engine;
Tires tires;
var description = 'No DI';
Car() {
engine = new Engine();
tires = new Tires();
}
//#enddocregion car-ctor
// Method using the engine and tires
drive() => '$description car with ${engine.cylinders} cylinders and ${tires.make} tires.';
}
//#enddocregion car

View File

@ -0,0 +1,7 @@
// #docregion
class Hero {
num id;
String name;
bool isSecret = false;
}

View File

@ -0,0 +1,21 @@
// #docregion
import 'package:angular2/core.dart';
import 'hero.dart';
import 'hero_service.dart';
@Component(
selector: 'hero-list',
template: '''
<div *ngFor="#hero of heroes">
{{hero.id}} - {{hero.name}}
({{hero.isSecret ? \'secret\' : \'public\'}})
</div>
''')
class HeroListComponent {
List<Hero> heroes;
//#docregion ctor-signature
HeroListComponent(HeroService heroService) : heroes = heroService.getHeroes();
//#enddocregion ctor-signature
}

View File

@ -0,0 +1,16 @@
// #docregion
import 'package:angular2/core.dart';
import 'hero.dart';
import 'mock_heroes.dart';
@Component(
selector: 'hero-list',
template: '''
<div *ngFor="#hero of heroes">
{{hero.id}} - {{hero.name}}
</div>
''')
class HeroListComponent {
List<Hero> heroes = HEROES;
}

View File

@ -0,0 +1,20 @@
// #docregion
import 'package:angular2/core.dart';
import 'hero.dart';
import 'hero_service.dart';
@Component(
selector: 'hero-list',
template: '''
<div *ngFor="#hero of heroes">
{{hero.id}} - {{hero.name}}
</div>
''')
class HeroListComponent {
List<Hero> heroes;
//#docregion ctor
HeroListComponent(HeroService heroService) : heroes = heroService.getHeroes();
//#enddocregion ctor
}

View File

@ -0,0 +1,22 @@
// #docregion
import 'package:angular2/core.dart';
import 'hero.dart';
import 'mock_heroes.dart';
import '../logger_service.dart';
@Injectable()
class HeroService {
// #docregion internals
Logger _logger;
bool _isAuthorized;
HeroService(this._logger, this._isAuthorized);
List<Hero> getHeroes() {
var auth = _isAuthorized ? 'authorized' : 'unauthorized';
_logger.log('Getting heroes for ${auth} user.');
return HEROES.where((hero) => _isAuthorized || !hero.isSecret).toList();
}
// #enddocregion internals
}

View File

@ -0,0 +1,8 @@
// #docregion
import 'hero.dart';
import 'mock_heroes.dart';
class HeroService {
List<Hero> getHeroes() => HEROES;
}

View File

@ -0,0 +1,20 @@
// #docregion
import 'package:angular2/core.dart';
import 'hero.dart';
import 'mock_heroes.dart';
import '../logger_service.dart';
@Injectable()
class HeroService {
Logger _logger;
//#docregion ctor
HeroService(this._logger);
//#enddocregion ctor
List<Hero> getHeroes() {
_logger.log('Getting heroes ...');
return HEROES;
}
}

View File

@ -0,0 +1,16 @@
// #docregion
import 'package:angular2/core.dart';
import 'hero_service.dart';
import '../logger_service.dart';
import '../user_service.dart';
// #docregion factory
heroServiceFactory(Logger logger, UserService userService) =>
new HeroService(logger, userService.user.isAuthorized);
// #enddocregion factory
// #docregion provider
const heroServiceProvider =
const Provider(HeroService, useFactory: heroServiceFactory, deps: const [Logger, UserService]);
// #enddocregion provider

View File

@ -0,0 +1,15 @@
// #docregion
import 'package:angular2/core.dart';
import 'hero_list_component.dart';
import 'hero_service_provider.dart';
@Component(
selector: 'my-heroes',
template: '''
<h2>Heroes</h2>
<hero-list></hero-list>
''',
providers: const [heroServiceProvider],
directives: const [HeroListComponent])
class HeroesComponent {}

View File

@ -0,0 +1,25 @@
// #docplaster
// #docregion
// #docregion v1
import 'package:angular2/core.dart';
import 'hero_list_component.dart';
// #enddocregion v1
import 'hero_service.dart';
// #docregion v1
@Component(
selector: 'my-heroes',
template: '''
<h2>Heroes</h2>
<hero-list></hero-list>
''',
// #enddocregion v1
// #docregion providers
providers: const [HeroService],
// #enddocregion providers
// #docregion v1
directives: const [HeroListComponent])
class HeroesComponent {}
// #enddocregion v1

View File

@ -0,0 +1,46 @@
// #docregion
import 'hero.dart';
List<Hero> HEROES = [
new Hero()
..id = 11
..isSecret = false
..name = 'Mr. Nice',
new Hero()
..id = 12
..isSecret = false
..name = 'Narco',
new Hero()
..id = 13
..isSecret = false
..name = 'Bombasto',
new Hero()
..id = 14
..isSecret = false
..name = 'Celeritas',
new Hero()
..id = 15
..isSecret = false
..name = 'Magneta',
new Hero()
..id = 16
..isSecret = false
..name = 'RubberMan',
new Hero()
..id = 17
..isSecret = false
..name = 'Dynama',
new Hero()
..id = 18
..isSecret = true
..name = 'Dr IQ',
new Hero()
..id = 19
..isSecret = true
..name = 'Magma',
new Hero()
..id = 20
..isSecret = true
..name = 'Tornado'
];

View File

@ -0,0 +1,58 @@
// #docplaster
//#docregion
import 'package:angular2/core.dart';
import 'car/car.dart';
import 'heroes/hero_service.dart';
import 'heroes/hero_service_provider.dart';
import 'logger_service.dart';
import 'package:dependency_injection/heroes/hero.dart';
//#docregion injector
@Component(
selector: 'my-injectors',
template: '''
<h2>Other Injections</h2>
<div id="car"> {{car.drive()}}</div>
<div id="hero">{{hero.name}}</div>
<div id="rodent">{{rodent}}</div>
''',
providers: const [
Car,
Engine,
Tires,
const Provider(HeroService, useFactory: heroServiceFactory),
Logger
])
class InjectorComponent {
Injector _injector;
InjectorComponent(this._injector) {
car = _injector.get(Car);
heroService = _injector.get(HeroService);
hero = heroService.getHeroes()[0];
}
Car car;
//#docregion get-hero-service
HeroService heroService;
//#enddocregion get-hero-service
Hero hero;
String get rodent {
var rous = _injector.getOptional(ROUS);
if (rous != null) {
throw new Exception('Aaaargh!');
}
return "R.O.U.S.'s? I don't think they exist!";
}
}
//#enddocregion injector
/**
* R.O.U.S. - Rodents Of Unusual Size
* // https://www.youtube.com/watch?v=BOv5ZjAOpC8
*/
class ROUS {}

View File

@ -0,0 +1,13 @@
// #docregion
import 'package:angular2/core.dart';
@Injectable()
class Logger {
List<String> logs = [];
void log(String message) {
logs.add(message);
print(message);
}
}

View File

@ -0,0 +1,360 @@
// Examples of provider arrays
//#docplaster
import 'package:angular2/core.dart';
import 'app_config.dart';
import 'heroes/hero_service_provider.dart';
import 'heroes/hero_service.dart';
import 'logger_service.dart';
import 'user_service.dart';
// #docregion import-optional
import 'package:angular2/core.dart' show Optional;
// #enddocregion import-optional
const template = '{{log}}';
//////////////////////////////////////////
@Component(selector: 'provider-1', template: '{{log}}', providers:
//#docregion providers-1
const [Logger]
//#enddocregion providers-1
)
class ProviderComponent1 {
String log;
ProviderComponent1(Logger logger) {
logger.log('Hello from logger provided with Logger class');
log = logger.logs[0];
}
}
//////////////////////////////////////////
@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(
selector: 'provider-3',
template: '{{log}}',
providers: const [const Provider(Logger, useClass: Logger)]
/*
//#docregion providers-3
const [provide(Logger, useClass: Logger)]
//#enddocregion providers-3
*/
)
class ProviderComponent3 {
String log;
ProviderComponent3(Logger logger) {
logger.log('Hello from logger provided with useClass');
log = logger.logs[0];
}
}
//////////////////////////////////////////
class BetterLogger extends Logger {}
@Component(selector: 'provider-4', template: '{{log}}', providers:
//#docregion providers-4
const [const Provider(Logger, useClass: BetterLogger)]
//#enddocregion providers-4
)
class ProviderComponent4 {
String log;
ProviderComponent4(Logger logger) {
logger.log('Hello from logger provided with useClass:BetterLogger');
log = logger.logs[0];
}
}
//////////////////////////////////////////
// #docregion EvenBetterLogger
@Injectable()
class EvenBetterLogger implements Logger {
UserService _userService;
List<String> logs = [];
EvenBetterLogger(this._userService);
log(String message) {
message = 'Message to ${ _userService.user.name}: ${ message}.';
print(message);
logs.add(message);
}
}
// #enddocregion EvenBetterLogger
@Component(selector: 'provider-5', template: '{{log}}', providers:
//#docregion providers-5
const [UserService, const Provider(Logger, useClass: EvenBetterLogger)]
//#enddocregion providers-5
)
class ProviderComponent5 {
String log;
ProviderComponent5(Logger logger) {
logger.log('Hello from EvenBetterlogger');
log = logger.logs[0];
}
}
//////////////////////////////////////////
class NewLogger extends Logger implements OldLogger {}
class OldLogger {
List<String> logs = [];
log(String message) {
throw new Exception('Should not call the old logger!');
}
}
@Component(selector: 'provider-6a', template: '{{log}}', providers:
//#docregion providers-6a
const [
NewLogger,
// Not aliased! Creates two instances of `NewLogger`
const Provider(OldLogger, useClass: NewLogger)
]
//#enddocregion providers-6a
)
class ProviderComponent6a {
String log;
ProviderComponent6a(NewLogger newLogger, OldLogger oldLogger) {
if (identical(newLogger, oldLogger)) {
throw new Exception('expected the two loggers to be different instances');
}
oldLogger.log('Hello OldLogger (but we want NewLogger)');
// The newLogger wasn't called so no logs[]
// display the logs of the oldLogger.
log = newLogger.logs == null || newLogger.logs.isEmpty ? oldLogger.logs[0] : newLogger.logs[0];
}
}
@Component(selector: 'provider-6b', template: '{{log}}', providers:
//#docregion providers-6b
const [
NewLogger,
// Alias OldLogger w/ reference to NewLogger
const Provider(OldLogger, useExisting: NewLogger)
//#enddocregion providers-6b
])
class ProviderComponent6b {
String log;
ProviderComponent6b(NewLogger newLogger, OldLogger oldLogger) {
if (!identical(newLogger, oldLogger)) {
throw new Exception('expected the two loggers to be the same instance');
}
oldLogger.log('Hello from NewLogger (via aliased OldLogger)');
log = newLogger.logs[0];
}
}
//////////////////////////////////////////
// #docregion silent-logger
// An object in the shape of the logger service
class SilentLogger /*implements Logger*/ {
const SilentLogger({this.logs});
final List<String> logs;
log(String message) {}
}
const silentLogger = const SilentLogger(
logs: const ['Silent logger says "Shhhhh!". Provided via "useValue"']);
// #enddocregion silent-logger
@Component(selector: 'provider-7', template: '{{log}}', providers:
//#docregion providers-7
const [const Provider(SilentLogger, useValue: silentLogger)]
//#enddocregion providers-7
/*
//#docregion providers-7-unchecked
const [const Provider(Logger, useValue: silentLogger)]
//#enddocregion providers-7-unchecked
*/
)
class ProviderComponent7 {
String log;
ProviderComponent7(SilentLogger logger) {
logger.log('Hello from logger provided with useValue');
log = logger.logs[0];
}
}
/////////////////
@Component(selector: 'provider-8', template: '{{log}}', providers: const [
const Provider(HeroService, useFactory: heroServiceFactory),
Logger,
UserService
])
class ProviderComponent8 {
// #docregion provider-8-ctor
ProviderComponent8(HeroService heroService);
// #enddocregion provider-8-ctor
// must be true else this component would have blown up at runtime
var log = 'Hero service injected successfully';
}
/////////////////
@Component(selector: 'provider-9a', template: '{{log}}', providers:
/*
// #docregion providers-9a-interface
// WOKRKS! Can use abstract class as provider token
[provide(Config, {useValue: CONFIG})]
// #enddocregion providers-9a-interface
*/
// #docregion providers-9a
// Use string as provider token
const [const Provider('app.config', useValue: CONFIG_HASH)]
//#enddocregion providers-9a
)
class ProviderComponent9a implements OnInit {
Config _config;
String log;
/*
// #docregion provider-9a-ctor-interface
// WORKS! Can inject using the abstract class as the parameter type
Config _config;
ProviderComponent9a(this._config);
// #enddocregion provider-9a-ctor-interface
*/
// #docregion provider-9a-ctor
// @Inject(token) to inject the dependency
ProviderComponent9a(@Inject('app.config') Map config) {
_config = new ConfigImpl(apiEndpoint: config['apiEndpoint'], title: config['title']);
}
// #enddocregion provider-9a-ctor
ngOnInit() {
log = '\'app.config\' Application title is ' + _config.title;
}
}
@Component(selector: 'provider-9b', template: '{{log}}', providers:
// #docregion providers-9b
const [const Provider(APP_CONFIG, useValue: CONFIG_HASH)]) // #enddocregion providers-9b
class ProviderComponent9b
implements OnInit {
Config _config;
String log;
// #docregion provider-9b-ctor
ProviderComponent9b(@Inject(APP_CONFIG) Map config) {
_config = new ConfigImpl(apiEndpoint: config['apiEndpoint'], title: config['title']);
}
// #enddocregion provider-9b-ctor
ngOnInit() {
log = 'APP_CONFIG Application title is ' + _config.title;
}
}
//////////////////////////////////////////
// Normal required logger
@Component(selector: 'provider-10a', template: '{{log}}',
//#docregion providers-logger
providers: const [Logger]
//#enddocregion providers-logger
)
class ProviderComponent10a {
String log;
ProviderComponent10a(Logger logger) {
logger.log('Hello from the required logger.');
log = logger.logs[0];
}
}
// Optional logger
@Component(selector: 'provider-10b', template: '{{log}}')
class ProviderComponent10b implements OnInit {
Logger _logger;
// #docregion provider-10-ctor
String log;
ProviderComponent10b(@Optional() this._logger);
// #enddocregion provider-10-ctor
ngOnInit() {
// #docregion provider-10-logger
// No logger? Make one!
if (_logger == null) {
_logger = new Logger();
// #enddocregion provider-10-logger
_logger.log('Optional logger was not available.');
} else {
_logger.log('Hello from the injected logger.');
log = _logger.logs[0];
}
log = _logger.logs[0];
}
}
/////////////////
@Component(
selector: 'my-providers',
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="p4"><provider-4></provider-4></div>
<div id="p5"><provider-5></provider-5></div>
<div id="p6a"><provider-6a></provider-6a></div>
<div id="p6b"><provider-6b></provider-6b></div>
<div id="p7"><provider-7></provider-7></div>
<div id="p8"><provider-8></provider-8></div>
<div id="p9a"><provider-9a></provider-9a></div>
<div id="p9b"><provider-9b></provider-9b></div>
<div id="p10a"><provider-10a></provider-10a></div>
<div id="p10b"><provider-10b></provider-10b></div>
''',
directives: const [
ProviderComponent1,
ProviderComponent2,
ProviderComponent3,
ProviderComponent4,
ProviderComponent5,
ProviderComponent6a,
ProviderComponent6b,
ProviderComponent7,
ProviderComponent8,
ProviderComponent9a,
ProviderComponent9b,
ProviderComponent10a,
ProviderComponent10b
])
class ProvidersComponent {}

View File

@ -0,0 +1,27 @@
// #docregion
import 'package:angular2/core.dart';
@Injectable()
class UserService {
UserService() {
user = _bob;
}
// Todo: get the user; don't 'new' it.
User _alice = new User('Alice', true);
User _bob = new User('Bob', false);
// initial user is Bob
User user;
// swaps users
User getNewUser() => user = user == _bob ? _alice : _bob;
}
class User {
String name;
bool isAuthorized;
User(this.name, [this.isAuthorized = false]);
}

View File

@ -0,0 +1,16 @@
name: dependency_injection
description: Dependency injection sample
version: 0.0.1
description: Dependency injection sample
dependencies:
angular2: ^2.0.0-beta.6
browser: ^0.10.0
transformers:
- angular2:
platform_directives:
- 'package:angular2/common.dart#COMMON_DIRECTIVES'
platform_pipes:
- 'package:angular2/common.dart#COMMON_PIPES'
entry_points: web/main.dart
dev_dependencies:
test: any

View File

@ -0,0 +1,34 @@
// A simple test
// More details will be in the testing chapter.
import 'package:angular2/angular2.dart';
import 'package:dependency_injection/heroes/hero.dart';
import 'package:dependency_injection/heroes/hero_list_component.dart';
import 'package:dependency_injection/heroes/hero_service.dart';
import 'package:test/test.dart';
///////////////////////////////////////
////#docregion spec
List<Hero> expectedHeroes = [
new Hero()
..id = 1
..name = 'hero1',
new Hero()
..id = 2
..name = 'hero2'
..isSecret = true
];
class HeroServiceMock implements HeroService {
@override
List<Hero> getHeroes() => expectedHeroes;
}
var mockService = new HeroServiceMock();
void main() {
test('should have heroes when HeroListComponent created', () {
var hlc = new HeroListComponent(mockService);
expect(hlc.heroes.length, expectedHeroes.length);
});
}
//#enddocregion spec

View File

@ -0,0 +1,15 @@
<!-- #docregion -->
<!DOCTYPE html>
<html>
<head>
<title>Dependency Injection</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="application/dart" src="main.dart"></script>
</head>
<body>
<my-app>Loading my-app ...</my-app>
<my-providers>Loading my-providers ...</my-providers>
</body>
</html>

View File

@ -0,0 +1,12 @@
//#docregion
import 'package:angular2/platform/browser.dart';
import 'package:dependency_injection/app_component.dart';
import 'package:dependency_injection/providers_component.dart';
main() {
//#docregion bootstrap
bootstrap(AppComponent);
//#enddocregion bootstrap
bootstrap(ProvidersComponent);
}

View File

@ -0,0 +1,10 @@
import 'package:angular2/platform/browser.dart';
import 'package:dependency_injection/app_component.dart';
import 'package:dependency_injection/heroes/hero_service.dart';
//#docregion bootstrap
main() {
// Injecting services in bootstrap works but is discouraged
bootstrap(AppComponent, [HeroService]);
//#enddocregion bootstrap
}

View File

@ -2,5 +2,10 @@ include ../../../../_includes/_util-fns
:marked
We're working on the Dart version of this chapter.
In the meantime, please read the
[TypeScript version of this chapter](/docs/ts/latest/guide/dependency-injection.html).
In the meantime, please see these resources:
* [Dependency Injection](/docs/ts/latest/guide/dependency-injection.html):
The TypeScript version of this chapter
* [Dart source code](https://github.com/angular/angular.io/tree/master/public/docs/_examples/dependency-injection/dart):
A preliminary version of the example code that will appear in this chapter