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 bower_components
jspm_packages jspm_packages
typings typings
packages **/packages
build build
pubspec.lock pubspec.lock
.pub .pub
.packages .packages
*.map *.map
.DS_Store .DS_Store
**/*.iml
.idea .idea
**/js/latest/api **/js/latest/api
**/ts/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 :marked
We're working on the Dart version of this chapter. We're working on the Dart version of this chapter.
In the meantime, please read the In the meantime, please see these resources:
[TypeScript version of this chapter](/docs/ts/latest/guide/dependency-injection.html).
* [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