Reputation: 1128
I have a big application using Dart (1.24.2) and angular dart (3.1.0). I decided to split the application into two packages: the first is a foundation layer and the second is the true application package. The idea is to be able to reuse the foundation layer in other projects. In the foundation layer I use several services (providers) that are global to the application and are widely used. Now, in the application layer I had the need to add some fields to some services. The problem I had is that you cannot use a component of the foundation layer that uses a service modified. The message that I get is: "EXCEPTION: No provider found for ." I cannot say that this is bug, but It would be helpful in creating angular modules. An example. I have generated (from Webstorm) an example application using Angular2: The Todo list application. Given this, I Have modified a little bit the "src/todo_list/todo_list_component.dart" source removing the TodoListService provider.
//providers: const [TodoListService],
and moving the declaration into the AppComponent class:
import 'src/todo_list/todo_list_service.dart';
// AngularDart info: https://webdev.dartlang.org/angular
// Components info: https://webdev.dartlang.org/components
@Component(
selector: 'my-app',
styleUrls: const ['app_component.css'],
templateUrl: 'app_component.html',
directives: const [materialDirectives, TodoListComponent],
providers: const [materialProviders, TodoListService],
)
class AppComponent {
This way the service is global to all components call by AppComponent.
Then I have generated a second project, always a TodoList example and made the same modifications as in the previous (globalizing the TodoListService).
Now, in the derived package I did the following: Added a reference to the foundation layer package; Cancelled the src/todo_list/todo_list_component.dart, .css and .html. This because I want to use the foundation layer package TodoList component. Added a field to the TodoListService:
import 'package:angular2/core.dart';
import 'package:angular_inject_subclass_base/src/todo_list/todo_list_service.dart' as base;
/// Mock service emulating access to a to-do list stored on a server.
@Injectable()
class TodoListService extends base.TodoListService {
String description;
}
Last modification, in the AppComponent source, I changed the reference to the TodoListComponent of the foundation layer:
import 'package:angular_inject_subclass_base/src/todo_list/todo_list_component.dart';
Trying to run the derived project I got the following error:
(anonymous function) EXCEPTION: No provider found for TodoListService. STACKTRACE:
0 _EmptyInjector.get (package:angular2/src/core/di/injector.dart:54:7)
1 _MapInjector.get (package:angular2/src/core/di/injector.dart:73:52) 2 ReflectiveInjectorImpl._getByKeyDefault (package:angular2/src/core/di/reflective_injector.dart:816:18)
3 ReflectiveInjectorImpl._getByKey (package:angular2/src/core/di/reflective_injector.dart:782:14)
4 ReflectiveInjectorImpl.get (package:angular2/src/core/di/reflective_injector.dart:529:17)
5 AppView.injectorGet (package:angular2/src/core/linker/app_view.dart:236:37)
6 DebugAppView.injectorGet (package:angular2/src/debug/debug_app_view.dart:98:31)
7 ViewAppComponent0.build (package:angular_inject_subclass_derived/app_component.template.dart:90:71)
8 AppView.create (package:angular2/src/core/linker/app_view.dart:180:12)
Is there any other way of doing this? Is it possible to change this behavior in Angular so that also a subclass of the provider can be injected instead of the original one?
Upvotes: 1
Views: 68
Reputation: 658017
You can provide subclasses using
providers: const [
materialProviders,
const Provider(base.TodoListService, useClass: TodoListService)
],
then when some class depends on base.TodoListService
, Angular will inject the subclass TodoListService
which will be compatible with the called constructor because it is a subclass.
TodoListService
alone is a short form (that will probably discontinued in Angular 5) for const Provider(TodoListService, useClass: TodoListService)
Upvotes: 2