Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

[WIP] Dart dependency injection #951

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,39 +1,46 @@
// #docplaster

// #docregion

// #docregion imports
import 'package:angular2/core.dart';
import 'package:angular2/angular2.dart';

import 'app_config.dart';
import 'car/car_component.dart';
import 'heroes/heroes_component.dart';
import 'app_config.dart';
import 'logger_service.dart';
import 'user_service.dart';

//PENDING: check whether we intend to hide injector_component.dart & providers_component.dart; if so, change docregion name?
// #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],
<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>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The \ seems redundant. Why single quote while elsewhere in the template double quotes are used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't notice that. You're right, " is better.

<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)]
providers: const [
Logger,
UserService,
const Provider(Config, useValue: CONFIG)
]
// #enddocregion providers
)
)
class AppComponent {
UserService _userService;
String title;
Expand All @@ -57,7 +64,8 @@ class AppComponent {
}

String get userInfo {
return 'Current user, ${user.name}, is ${isAuthorized ? "" : "not"} authorized. ';
return 'Current user, ${user.name}, is'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use arrow syntax here.

'${isAuthorized ? "" : " not"} authorized. ';
}
}
// #enddocregion
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
// Early versions

// #docregion
import 'package:angular2/core.dart';
import 'package:angular2/angular2.dart';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are the imports changed to angular2/angular2.dart? AFAIR it was suggested not too long ago to prefer core.dart.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed that recommendation. Can you tell me more about it? When talking to an internal engineer who uses Angular (but isn't on the Angular team), it seemed to us that angular2.dart was better because you wouldn't have to think twice about which files to include. (And tree shaking would make it not matter if you included more than you needed.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zoechi Would you be able to dig up that recommendation? Would be very interested to see the rationale.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea where exactly I saw this. It was a while back when the public API was reworked about 2 months ago. I don't think it's too important.


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>
''',
<h1>{{title}}</h1>
<my-car></my-car>
<my-heroes></my-heroes>''',
directives: const [CarComponent, HeroesComponent])
class AppComponent {
var title = 'Dependency Injection';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
// #docregion

// #docregion imports
import 'package:angular2/core.dart';
import 'package:angular2/angular2.dart';

import 'app_config.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>
''',
<h1>{{title}}</h1>
<my-car></my-car>
<my-heroes></my-heroes>''',
directives: const [
CarComponent,
HeroesComponent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//#docregion

// #docregion
// #docregion token
import 'package:angular2/core.dart';
import 'package:angular2/angular2.dart';

const APP_CONFIG = const OpaqueToken('app.config');
// #enddocregion token
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// #docregion

import 'package:angular2/core.dart';
import 'package:angular2/angular2.dart';

// #docregion engine
class Engine {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
// #docregion
import 'package:angular2/angular2.dart';

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_factory.dart';
import 'car_injector.dart';
import 'car_no_di.dart' as carNoDi;

@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>
''',
<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;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
// 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
Expand All @@ -21,11 +18,10 @@ class Engine2 implements Engine {

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());
Expand All @@ -43,11 +39,9 @@ class MockEngine extends Engine {
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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// #docregion

import 'car.dart';

// BAD pattern!
class CarFactory {
Car createCar() {
var car = new Car(createEngine(), createTires());
Expand All @@ -10,6 +10,5 @@ class CarFactory {
}

Engine createEngine() => new Engine();

Tires createTires() => new Tires();
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// #docplaster

//#docregion
import 'package:angular2/core.dart';
import 'car.dart';
import 'package:angular2/angular2.dart';

import '../logger_service.dart';
import 'car.dart';

//#docregion injector
Car useInjector() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ class 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.';
drive() => '$description car with '
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return type.

Also, this is against the general Dart style guide as we're using an action verb but not actually performing any changes.. Can we consider renaming this and making it a get?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll check, but I believe we're just following the original TypeScript example here.

We follow Dart conventions where possible (e.g. using types for APIs), while trying to keep the code similar (e.g. names).

'${engine.cylinders} cylinders and ${tires.make} tires.';
}
//#enddocregion car
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// #docregion

class Hero {
num id;
String name;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
// #docregion
import 'package:angular2/angular2.dart';

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>
''')
<div *ngFor="#hero of heroes">
{{hero.id}} - {{hero.name}}
({{hero.isSecret ? \'secret\' : \'public\'}})
</div>''')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant \

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. Thanks for catching that.

class HeroListComponent {
List<Hero> heroes;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
// #docregion
import 'package:angular2/angular2.dart';

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>
''')
<div *ngFor="#hero of heroes">
{{hero.id}} - {{hero.name}}
</div>''')
class HeroListComponent {
List<Hero> heroes = HEROES;
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
// #docregion
import 'package:angular2/angular2.dart';

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>
''')
<div *ngFor="#hero of heroes">
{{hero.id}} - {{hero.name}}
</div>''')
class HeroListComponent {
List<Hero> heroes;

//#docregion ctor
HeroListComponent(HeroService heroService) : heroes = heroService.getHeroes();
HeroListComponent(HeroService heroService)
: heroes = heroService.getHeroes();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make heroes final?

//#enddocregion ctor
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// #docregion
import 'package:angular2/angular2.dart';

import 'package:angular2/core.dart';
import '../logger_service.dart';
import 'hero.dart';
import 'mock_heroes.dart';
import '../logger_service.dart';

@Injectable()
class HeroService {
Expand All @@ -15,7 +15,7 @@ class HeroService {

List<Hero> getHeroes() {
var auth = _isAuthorized ? 'authorized' : 'unauthorized';
_logger.log('Getting heroes for ${auth} user.');
_logger.log('Getting heroes for $auth user.');
return HEROES.where((hero) => _isAuthorized || !hero.isSecret).toList();
}
// #enddocregion internals
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// #docregion

import 'hero.dart';
import 'mock_heroes.dart';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// #docregion
import 'package:angular2/angular2.dart';

import 'package:angular2/core.dart';
import '../logger_service.dart';
import 'hero.dart';
import 'mock_heroes.dart';
import '../logger_service.dart';

@Injectable()
class HeroService {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
// #docregion
import 'package:angular2/angular2.dart';

import 'package:angular2/core.dart';
import 'hero_service.dart';
import '../logger_service.dart';
import '../user_service.dart';
import 'hero_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]);
const heroServiceProvider = const Provider(HeroService,
useFactory: heroServiceFactory,
deps: const [Logger, UserService]);
// #enddocregion provider
Loading