J'utilise le didacticiel Heroes dans la documentation Angular 2 pour expérimenter. Cependant, je suis arrivé à un point où je ne comprends pas ce qui se passe avec cette erreur:
Uncaught (in promise): TypeError: Cannot read property 'query' of null
in browser_adapter.ts:88
.
Les deux pièces impliquées sont la HeroDetailComponent
et la HeroService
.
import { Component, OnInit } from '@angular/core';
import { RouteParams } from '@angular/router-deprecated';
import { Hero, HeroService } from '../index';
@Component({
selector: 'my-hero-detail',
templateUrl: ...
styleUrls: [...]
})
export class HeroDetailComponent implements OnInit {
hero: Hero;
// TEMPORARY FIX:
_heroService = new HeroService(); // Avoids injection
// constructor(private _heroService: HeroService,
// private _routeParams: RouteParams) {}
constructor(private _routeParams: RouteParams) {}
ngOnInit() {
let id = +this._routeParams.get('id');
console.log(id);
}
}
Quand j'utilise ce code, ça marche. Mais lorsque je change de constructeur et que j'utilise celui avec l'injection HeroService
, j'obtiens l'erreur mentionnée précédemment.
@Injectable()
export class HeroService {
getHeroes() {
return HEROES;
}
getHero(id: number) {
return new Hero(1, 'Name', 'Power', 'AlterEgo');
}
}
Pendant que j'essayais de comprendre ce qui se passait, j'ai supprimé tout le code relatif aux promesses. Cependant, j'ai toujours la même erreur. Tout se passe bien, c'est une erreur d'exécution. HeroService
et RouteParams
sont fournis dans un composant parent.
Deux questions:
J'ai tendance à penser que c'est un bug dans Angular 2, mais je ne sais pas comment faire pour que ce ne soit pas une erreur de ma part. Merci d'avance.
MISES À JOUR:
J'ai ajouté le code de correctif temporaire (qui évite l'injection et ne constitue donc pas une solution à cette question, car j'aimerais que l'injection fonctionne correctement).
Ceci est un Plunker avec une version approximative du code que j'essaie. Je ne pouvais pas le faire fonctionner correctement, mais il peut être utile de diagnostiquer le problème en regardant dans le code.
Je vois le problème suivant: HeroComponent
dépend de HeroDetailsComponent
, mais HeroDetailsComponent
est exporté afterwards dans le fichier app/heroes/index.ts
.
Quelqu'un a signalé un problème avec ce type d'installation ici
Dans le "tsconfig.json", définissez le paramètre "emitDecoratorMetadata" de la section "compilerOptions" sur la valeur "true".
J'ai eu cette erreur avec RC1 angulaire quand j'injectais FormBuilder
dans le constructeur comme ceci:
export class App {
constructor(public formBuilder: FormBuilder) {}
}
Mais je ne l'avais pas import
auparavant! Il suffit d'ajouter que cela résout le problème:
import { FormBuilder } from '@angular/common'
Essayez avec ces compilerOptions dans "tsconfig.json". Cela a fonctionné pour moi (version 2.0.0-rc.1 de angular).
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true },
J'ai eu le même problème avec les injectables (même erreur) et le correctif a fait l'affaire pour les services mais pas pour http. J'ai modifié mes options sur la base d'un tutoriel de ng-book2 et cela a finalement fonctionné.
Dans mon cas, je résous ce problème en utilisant @Inject
décorator. Essaye ça:
import {Inject} from '@angular/core'
constructor(@Inject(HeroService) private _heroService: HeroService,
@Inject(RouteParams) private _routeParams: RouteParams) {}
Mon projet est configuré avec JSPM et c'est la seule façon de travailler avec l'injection de dépendance, je ne sais pas pourquoi, quelqu'un a une explication?
Edité: j'ai trouvé la solution. Dans mon cas, je dois ajouter cette configuration dans le fichier config.js
System.config({
baseURL: "",
defaultJSExtensions: true,
transpiler: "TypeScript",
typescriptOptions: {
"target": "es5",
"emitDecoratorMetadata": true
},
paths: {
"npm:*": "jspm_packages/npm/*",
....
Maintenant je peux enlever le décorateur @Inject et cette phrase fonctionne correctement
constructor(private _heroService: HeroService,
private _routeParams: RouteParams) {}
La clé est emitDecoratorMetadata: true
La réponse correcte à partir de RC1 est d’ajouter la @Inject(Service) private service:Service
à chaque fois que vous injectez des services.
Cela m'a causé beaucoup de maux de tête après ma mise à niveau lundi vers RC1.