Soy nuevo en Angular 2 y TypeScript y estoy tratando de seguir las mejores prácticas.
En lugar de usar un modelo de JavaScript simple ({}), estoy intentando crear una clase de TypeScript.
Sin embargo, a Angular 2 no parece gustarle.
Mi codigo es:
import { Component, Input } from "@angular/core";
@Component({
selector: "testWidget",
template: "<div>This is a test and {{model.param1}} is my param.</div>"
})
export class testWidget {
constructor(private model: Model) {}
}
class Model {
param1: string;
}
y lo estoy usando como:
import { testWidget} from "lib/testWidget";
@Component({
selector: "myComponent",
template: "<testWidget></testWidget>",
directives: [testWidget]
})
Recibo un error de Angular:
EXCEPCIÓN: No se pueden resolver todos los parámetros para testWidget: (?).
Entonces pensé, el modelo aún no está definido ... ¡Lo moveré a la parte superior!
Excepto que ahora obtengo la excepción:
EXCEPCIÓN ORIGINAL: ¡No hay proveedor para Model!
¿Cómo logro esto?
Editar: Gracias a todos por la respuesta. Me llevó al camino correcto.
Para inyectar esto en el constructor, necesito agregarlo a los proveedores en el componente.
Esto parece funcionar:
import { Component, Input } from "@angular/core";
class Model {
param1: string;
}
@Component({
selector: "testWidget",
template: "<div>This is a test and {{model.param1}} is my param.</div>",
providers: [Model]
})
export class testWidget {
constructor(private model: Model) {}
}
fuente
providers: [Model]
. Además, según la demostración de Angular 2 Tour of Hero, debe usarlo como una propiedad en lugar de un inyectable, ya que esa funcionalidad generalmente está reservada para clases más complejas, como los servicios.new
). Es que no se llamará al constructor del modelo. Y esoinstanceOf Model
será falsonew
el otro día y me gusta para casos simples como este.angular-cli
, puede llamarng g class model
y lo generará por usted.model
siendo reemplazado por el nombre que desee.El problema radica en que no ha agregado
Model
ni abootstrap
(lo que lo convertirá en un singleton) ni a laproviders
matriz de la definición de su componente:@Component({ selector: "testWidget", template: "<div>This is a test and {{param1}} is my param.</div>", providers : [ Model ] }) export class testWidget { constructor(private model: Model) {} }
Y sí, debe definir por
Model
encima deComponent
. Pero mejor sería ponerlo en su propio archivo.Pero si desea que sea solo una clase desde la que puede crear múltiples instancias, es mejor que use
new
.@Component({ selector: "testWidget", template: "<div>This is a test and {{param1}} is my param.</div>" }) export class testWidget { private model: Model = new Model(); constructor() {} }
fuente
providers
matriz?No Provider for Model
si no lo agrego a la matriz de proveedoresexport
antes deModel
clase?En su caso, tiene el modelo en la misma página, pero lo tiene declarado después de su clase Componente, por lo que debe usarlo
forwardRef
para hacer referenciaClass
. No prefiera hacer esto, siempre tenga elmodel
objeto en un archivo separado.export class testWidget { constructor(@Inject(forwardRef(() => Model)) private service: Model) {} }
Además, debe cambiar la interpolación de vista para hacer referencia al objeto correcto
Lo mejor que debe hacer es que puede hacer que su
Model
Clase se defina en un archivo diferente y luego importarlo cuando lo necesite. También tengaexport
antes su nombre de clase, para que pueda importarlo.import { Model } from './model';
fuente
mi codigo es
import { Component } from '@angular/core'; class model { username : string; password : string; } @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { username : string; password : string; usermodel = new model(); login(){ if(this.usermodel.username == "admin"){ alert("hi"); }else{ alert("bye"); this.usermodel.username = ""; } } }
y el html es así:
<div class="login"> Usernmae : <input type="text" [(ngModel)]="usermodel.username"/> Password : <input type="text" [(ngModel)]="usermodel.password"/> <input type="button" value="Click Me" (click)="login()" /> </div>
fuente
export class Car { id: number; make: string; model: string; color: string; year: Date; constructor(car) { { this.id = car.id; this.make = car.make || ''; this.model = car.model || ''; this.color = car.color || ''; this.year = new Date(car.year).getYear(); } } }
El || puede volverse muy útil para objetos de datos muy complejos a datos predeterminados que no existen.
. .
En su archivo component.ts o service.ts, puede deserializar los datos de respuesta en el modelo:
// Import the car model import { Car } from './car.model.ts'; // If single object car = new Car(someObject); // If array of cars cars = someDataToDeserialize.map(c => new Car(c));
fuente
Puede usar el angular-cli como sugieren los comentarios en la respuesta de @ brendon.
Quizás también quieras probar:
ng g class modelsDirectoy/modelName --type=model /* will create src/app/modelsDirectoy ├── modelName.model.ts ├── ... ... */
Tenga en cuenta
ng g class
:! ==ng g c
Sin embargo, puede usarlo
ng g cl
como atajo dependiendo de su versión de angular-cli.fuente
Me doy cuenta de que esta es una pregunta algo más antigua, pero solo quería señalar que ha agregado la variable del modelo a su clase de widget de prueba de manera incorrecta. Si necesita una variable de modelo, no debería intentar pasarla a través del constructor del componente. Solo tiene la intención de aprobar servicios u otros tipos de inyectables de esa manera. Si está creando una instancia de su widget de prueba dentro de otro componente y necesita pasar un objeto de modelo como, le recomendaría usar el núcleo angular OnInit y los patrones de diseño de entrada / salida.
Como ejemplo, su código realmente debería verse así:
import { Component, Input, OnInit } from "@angular/core"; import { YourModelLoadingService } from "../yourModuleRootFolderPath/index" class Model { param1: string; } @Component({ selector: "testWidget", template: "<div>This is a test and {{model.param1}} is my param.</div>", providers: [ YourModelLoadingService ] }) export class testWidget implements OnInit { @Input() model: Model; //Use this if you want the parent component instantiating this //one to be able to directly set the model's value private _model: Model; //Use this if you only want the model to be private within //the component along with a service to load the model's value constructor( private _yourModelLoadingService: YourModelLoadingService //This service should //usually be provided at the module level, not the component level ) {} ngOnInit() { this.load(); } private load() { //add some code to make your component read only, //possibly add a busy spinner on top of your view //This is to avoid bugs as well as communicate to the user what's //actually going on //If using the Input model so the parent scope can set the contents of model, //add code an event call back for when model gets set via the parent //On event: now that loading is done, disable read only mode and your spinner //if you added one //If using the service to set the contents of model, add code that calls your //service's functions that return the value of model //After setting the value of model, disable read only mode and your spinner //if you added one. Depending on if you leverage Observables, or other methods //this may also be done in a callback } }
Una clase que es esencialmente solo una estructura / modelo no debe inyectarse, porque significa que solo puede tener una instancia compartida única de esa clase dentro del alcance que se proporcionó. En este caso, eso significa que el inyector de dependencias crea una única instancia de Model cada vez que se crea una instancia de testWidget. Si se proporcionara a nivel de módulo, solo tendría una instancia compartida entre todos los componentes y servicios dentro de ese módulo.
En su lugar, debe seguir las prácticas estándar orientadas a objetos y crear una variable de modelo privado como parte de la clase, y si necesita pasar información a ese modelo cuando crea una instancia de la instancia, debe ser manejada por un servicio (inyectable) proporcionado por el módulo padre. Así es como se pretende que tanto la inyección de dependencia como la comunicación se realicen en angular.
Además, como algunos de los otros mencionaron, debe declarar sus clases modelo en un archivo separado e importar la clase.
Recomendaría encarecidamente volver a la referencia de documentación angular y revisar las páginas básicas sobre las diversas anotaciones y tipos de clases: https://angular.io/guide/architecture
Debe prestar especial atención a las secciones sobre módulos, componentes y servicios / inyección de dependencia, ya que son esenciales para comprender cómo usar Angular a nivel arquitectónico. Angular es un lenguaje de arquitectura muy pesada porque es de muy alto nivel. La separación de preocupaciones, las fábricas de inyección de dependencia y el control de versiones de javascript para la comparabilidad del navegador se manejan principalmente por usted, pero debe usar la arquitectura de su aplicación correctamente o encontrará que las cosas no funcionan como espera.
fuente
cree model.ts en su directorio de componentes como se muestra a continuación
export module DataModel { export interface DataObjectName { propertyName: type; } export interface DataObjectAnother { propertyName: type; } }
luego, en su componente, importe arriba como, importe {DataModel} desde './model';
export class YourComponent { public DataObject: DataModel.DataObjectName; }
su DataObject debe tener todas las propiedades de DataObjectName.
fuente