content - page title angular 4
Inyectables en Angular2 (3)
Mi configuración: estoy ejecutando WebStorm 10.0.2 en Windows, utilizando TypeScript 1.5 beta (compilado para ES5) y node / npm.
Gracias a la ayuda de PSL, encontré varios problemas con mi configuración. No estaban relacionados con el código, por ejemplo, no al orden de las definiciones de clase, etc. Solo para que quede constancia, quisiera resumir los problemas que tuve. La mayoría de ellos han sido mencionados por PSL, pero tal vez otras personas tengan los mismos problemas, por ejemplo, relacionados con el compilador en WebStorm.
Aquí están los problemas que tuve:
Aunque configuré WebStorm para usar TypeScript 1.5 instalado vía npm, se utilizó una versión anterior (1.3), ya que también estaba instalada en mi sistema (creo que junto con Visual Studio) y registrada en la variable
%path%
Configuré WebStorm para usar una "Versión de compilación personalizada" para TypeScript (en configuraciones / Idiomas y Frameworks / TypeScript), con los siguientes argumentos:
-emitDecoratorMetadata -m commonjs -t es5 -sourceMap
. Esto de alguna manera no funciona ... No estoy seguro, si está relacionado con un problema en WebStorm. Sin el indicador-emitDecoratorMetadata
compilado, pero losinjectables
no funcionaron.[Actualización, 9. de junio de 2015: Sí, está relacionado con un problema en WebStorm]
Sin embargo, necesito el
-emitDecoratorMetadata
-flag para que losinjectables
en Angular2 funcionen.Mi solución fue agregar un "File Watcher" personalizado en WebStorm (en lugar de utilizar la función "Compilador incorporado") con los siguientes argumentos:
-emitDecoratorMetadata -m commonjs -t es5 --sourceMap $FilePath$
Lecciones aprendidas al trabajar con Angular2, TypeScript 1.5 y WebStorm:
Asegúrese de que TypeScript 1.5 sea realmente la versión que se utiliza para compilar los archivos ts (por ejemplo, en su IDE).
Asegúrese de que se especifique
-emitDecoratorMetadata
.No hace la diferencia, si las clases se definen en un orden específico o en archivos propios, etc.-> ¡El orden sí importa! Dividir las clases / componentes en diferentes archivos resuelve el problema y generalmente conduce a mejores archivos que se pueden mantener.
¡Gracias nuevamente a PSL por su valiosa contribución!
Estoy jugando con Angular2. Como base, utilicé el proyecto de inicio rápido de la página angular.io .
Todo parece funcionar bien, pero tan pronto como intento inyectar un servicio ( ItemService
) en mi AppComponent
obtengo la siguiente excepción:
Error durante la instanciación de Token (ComponentRef) !. ERROR ORIGINAL: No se pueden resolver todos los parámetros para AppComponent. Asegúrese de que todos tengan un tipo válido o anotaciones.
He visto problemas similares en Internet (incluido stackoverflow, por ejemplo, esta publicación ), pero ninguno de ellos parece resolver mi problema. ¿Algún cuerpo tiene alguna idea, cuál podría ser el problema?
También he visto algunas soluciones (por ejemplo, las del repositorio Angular2) que decoran la clase inyectable con la anotación Injectable
. Sin embargo, esto no funciona para mí, ya que no está definido en angular.d.ts
. ¿Estoy usando una versión incorrecta?
Puede encontrar mi solución siguiendo a Plunker: http://plnkr.co/edit/7kK1BtcuEHjaspwLTmsg
Para el registro, también puede encontrar mis dos archivos a continuación. Tenga en cuenta que la aplicación.js de Plunker es el archivo JavaScript generado a partir de mi archivo TypeScript a continuación, la excepción es siempre la misma.
index.html
:
<html>
<head>
<title>Testing Angular2</title>
<script src="https://github.jspm.io/jmcriffey/[email protected]/traceur-runtime.js"></script>
<script src="https://jspm.io/[email protected]"></script>
<script src="https://code.angularjs.org/2.0.0-alpha.23/angular2.dev.js"></script>
</head>
<body>
<app></app>
<script>
System.import(''js/app'');
</script>
</body>
</html>
js/app.ts
:
/// <reference path="../../typings/angular2/angular2.d.ts" />
import {Component, View, bootstrap, For, If} from "angular2/angular2";
class Item {
id:number;
name:string;
constructor(id:number, name:string) {
this.id = id;
this.name = name;
}
}
class ItemService {
getItems() {
return [
new Item(1, "Bill"),
new Item(2, "Bob"),
new Item(3, "Fred")
];
}
}
@Component({
selector: ''app'',
injectables: [ItemService]
})
@View({
template: `<h1>Testing Angular2</h1>
<ul>
<li *for="#item of items">
{{item.id}}: {{item.name}} |
<a href="javascript:void(0);" (click)="toggleSelected(item);">
{{selectedItem == item ? "unselect" : "select"}}
</a>
</li>
</ul>
<item-details *if="selectedItem" [item]="selectedItem"></item-details>`,
directives: [For, If, DetailComponent]
})
class AppComponent {
items:Item[];
selectedItem:Item;
constructor(itemService:ItemService) {
this.items = itemService.getItems();
}
toggleSelected(item) {
this.selectedItem = this.selectedItem == item ? null : item;
}
}
@Component({
selector: ''item-details'',
properties: {
item: "item"
}
})
@View({
template: `<span>You selected {{item.name}}</span>`
})
class DetailComponent {
item:Item;
}
bootstrap(AppComponent);
Gracias de antemano por cualquier idea!
Me enfrenté al mismo problema. A continuación se muestra la resolución:
- --emitDecoratorMetadata se perdió en tsc
- Si estaba inyectando el servicio desde el mismo archivo, estaba fallando, pero cuando puse el servicio es otro archivo y cuando lo importé, comenzó a funcionar. probablemente error en la versión Angular2 que estaba usando.
Verifique un par de cosas:
1) Asegúrese de estar utilizando la versión correcta de mecanografiado (1.5.x) instalado desde la ubicación de su paquete. () Si tiene instaladas versiones anteriores de mecanografiado, simplemente usar el comando "tsc" podría estar apuntando a la ubicación existente (<1.5) desde la ruta del entorno.
2) Asegúrese de utilizar el --emitDecoratorMetadata
con el comando tsc. Es necesario para que la salida de JavaScript cree los metadatos para los decoradores.
3) Error - Cannot read property ''annotations'' of undefined
porque la directiva AppComponent
tiene una dependencia en DetailComponent
que aún no se ha definido (en el momento en que la función sincrónica __decorate(
se resuelve para resolver las dependencias) y la forma en que TS compila la variable con DetailComponent
es indefinido entonces (El IIFE para el que está debajo aún no se ha ejecutado). Intente mover la declaración de DetailComponent
antes de AppComponent
. O simplemente AppComponent
a un archivo diferente e impórtelo.
@Component({
selector: ''item-details'',
properties: {
item: "item"
}
})
@View({
template: `<span>You selected {{item.name}}</span>`
})
class DetailComponent {
item:Item;
}
@Component({
selector: ''app'',
injectables: [ItemService]
})
@View({
template: `<h1>Testing Angular2</h1>
<ul>
<li *for="#item of items">
{{item.id}}: {{item.name}} |
<a href="#" (click)="toggleSelected(item);">
{{selectedItem == item ? "unselect" : "select"}}
</a>
</li>
</ul>
<item-details *if="selectedItem" [item]="selectedItem"></item-details>`,
directives: [For, If, DetailComponent]
})
class AppComponent {
items:Item[];
selectedItem:Item;
constructor(itemService:ItemService) {
this.items = itemService.getItems();
}
toggleSelected(item) {
this.selectedItem = this.selectedItem == item ? null : item;
return false;
}
}
bootstrap(AppComponent);
Editar
A partir del a26 angular, si tiene problemas con respecto a seguir la documentación actual (a partir de ahora), siga este enlace si es útil, ya que hay algunos cambios relevantes.