parent
ee5a4e131a
commit
1ac9316171
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
*/
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,7 @@
|
|||
// #docregion
|
||||
|
||||
class Hero {
|
||||
num id;
|
||||
String name;
|
||||
bool isSecret = false;
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// #docregion
|
||||
|
||||
import 'hero.dart';
|
||||
import 'mock_heroes.dart';
|
||||
|
||||
class HeroService {
|
||||
List<Hero> getHeroes() => HEROES;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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 {}
|
|
@ -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
|
|
@ -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'
|
||||
];
|
|
@ -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 {}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 {}
|
|
@ -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]);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue