Angular2 Dart: Dividing a project in packages does not allow to reuse base components with modified providers

Issue

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?

Solution

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)

Answered By – Günter Zöchbauer

Answer Checked By – Marilyn (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *