Ich bin neu in Angular 2 und TypeScript und versuche, Best Practices zu befolgen.
Anstatt ein einfaches JavaScript-Modell ({}) zu verwenden, versuche ich, eine TypeScript-Klasse zu erstellen.
Angular 2 scheint es jedoch nicht zu mögen.
Mein Code lautet:
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;
}
und ich benutze es als:
import { testWidget} from "lib/testWidget";
@Component({
selector: "myComponent",
template: "<testWidget></testWidget>",
directives: [testWidget]
})
Ich erhalte eine Fehlermeldung von Angular:
AUSNAHME: Es können nicht alle Parameter für testWidget aufgelöst werden: (?).
Also dachte ich, Modell ist noch nicht definiert ... Ich werde es nach oben verschieben!
Außer jetzt bekomme ich die Ausnahme:
ORIGINAL AUSNAHME: Kein Anbieter für Model!
Wie schaffe ich das?
Edit: Danke an alle für die Antwort. Es führte mich auf den richtigen Weg.
Um dies in den Konstruktor einzufügen, muss ich es den Anbietern auf der Komponente hinzufügen.
Dies scheint zu funktionieren:
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) {}
}
quelle
providers: [Model]
. Gemäß der Angular 2 Tour of Hero-Demo sollten Sie sie nur als Eigenschaft anstelle einer injizierbaren verwenden, da diese Funktionalität normalerweise komplexeren Klassen wie Diensten vorbehalten ist.new
). Ist das, dass der Konstrukteur des Modells nicht aufgerufen wird. Und dasinstanceOf Model
wird falsch seinnew
und mag sie für einfache Fälle wie diesen.angular-cli
, können Sie anrufenng g class model
und es wird es für Sie generieren.model
durch eine beliebige Benennung ersetzt werden.Das Problem liegt darin, dass Sie
Model
weder dembootstrap
(was es zu einem Singleton macht) noch demproviders
Array Ihrer Komponentendefinition hinzugefügt haben :@Component({ selector: "testWidget", template: "<div>This is a test and {{param1}} is my param.</div>", providers : [ Model ] }) export class testWidget { constructor(private model: Model) {} }
Und ja, Sie sollten
Model
über dem definierenComponent
. Aber besser wäre es, es in seine eigene Datei zu legen.Wenn Sie jedoch möchten, dass es sich nur um eine Klasse handelt, aus der Sie mehrere Instanzen erstellen können, verwenden Sie diese einfach
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() {} }
quelle
providers
Array?No Provider for Model
wenn ich sie nicht zum Anbieter-Array hinzufügeexport
vor demModel
Unterricht?In Ihrem Fall befindet sich das Modell auf derselben Seite, aber Sie haben es nach Ihrer Komponentenklasse deklariert. Sie müssen es also verwenden, um darauf
forwardRef
zu verweisenClass
. Ziehen Sie dies nicht vor, sondern haben Sie dasmodel
Objekt immer in einer separaten Datei.export class testWidget { constructor(@Inject(forwardRef(() => Model)) private service: Model) {} }
Zusätzlich müssen Sie Ihre Ansichtsinterpolation ändern, um auf das richtige Objekt zu verweisen
Besser ist es, wenn Sie Ihre
Model
Klasse in einer anderen Datei definieren lassen und sie dann importieren, wenn Sie dies benötigen. Habenexport
Sie auch vor Ihnen Klassennamen, damit Sie ihn importieren können.import { Model } from './model';
quelle
Mein Code ist
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 = ""; } } }
und das HTML geht so:
<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>
quelle
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(); } } }
Die || kann für sehr komplexe Datenobjekte sehr nützlich sein, wenn Standarddaten nicht vorhanden sind.
. .
In Ihrer Datei component.ts oder service.ts können Sie Antwortdaten in das Modell deserialisieren:
// 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));
quelle
Sie können das Angular-Cli verwenden, wie die Kommentare in der Antwort von @ brendon nahe legen.
Vielleicht möchten Sie auch versuchen:
ng g class modelsDirectoy/modelName --type=model /* will create src/app/modelsDirectoy ├── modelName.model.ts ├── ... ... */
ng g class
Beachtenng g c
Sie : ! == Sie können jedoch
ng g cl
abhängig von Ihrer Angular-Cli-Version als Verknüpfung verwenden.quelle
Mir ist klar, dass dies eine etwas ältere Frage ist, aber ich wollte nur darauf hinweisen, dass Sie die Modellvariable Ihrer Test-Widget-Klasse falsch hinzugefügt haben. Wenn Sie eine Modellvariable benötigen, sollten Sie nicht versuchen, sie über den Komponentenkonstruktor zu übergeben. Sie sollen nur Dienste oder andere Arten von Injektionsmitteln auf diese Weise weitergeben. Wenn Sie Ihr Test-Widget innerhalb einer anderen Komponente instanziieren und ein Modellobjekt als übergeben müssen, würde ich die Verwendung der Entwurfsmuster OnInit und Input / Output mit eckigem Kern empfehlen.
Als Beispiel sollte Ihr Code wirklich so aussehen:
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 } }
Eine Klasse, die im Wesentlichen nur eine Struktur / ein Modell ist, sollte nicht eingefügt werden, da dies bedeutet, dass Sie nur eine einzige gemeinsam genutzte Instanz dieser Klasse innerhalb des bereitgestellten Bereichs haben können. In diesem Fall bedeutet dies, dass jedes Mal, wenn testWidget instanziiert wird, eine einzelne Instanz von Model vom Abhängigkeitsinjektor erstellt wird. Wenn es auf Modulebene bereitgestellt würde, hätten Sie nur eine einzige Instanz, die von allen Komponenten und Diensten innerhalb dieses Moduls gemeinsam genutzt wird.
Stattdessen sollten Sie den objektorientierten Standardpraktiken folgen und eine private Modellvariable als Teil der Klasse erstellen. Wenn Sie beim Instanziieren der Instanz Informationen an dieses Modell übergeben müssen, sollten diese von einem Dienst (injizierbar) verwaltet werden, der von bereitgestellt wird das übergeordnete Modul. Auf diese Weise sollen sowohl die Abhängigkeitsinjektion als auch die Kommunikation im Winkel ausgeführt werden.
Wie einige der anderen erwähnt, sollten Sie Ihre Modellklassen auch in einer separaten Datei deklarieren und die Klasse importieren.
Ich würde dringend empfehlen, zur Referenz zur eckigen Dokumentation zurückzukehren und die Basisseiten zu den verschiedenen Anmerkungen und Klassentypen zu lesen: https://angular.io/guide/architecture
Beachten Sie insbesondere die Abschnitte zu Modulen, Komponenten und Diensten / Abhängigkeitsinjektion, da diese für das Verständnis der Verwendung von Angular auf architektonischer Ebene von entscheidender Bedeutung sind. Angular ist eine sehr architekturintensive Sprache, weil sie so hoch ist. Die Trennung von Bedenken, Abhängigkeitsinjektionsfabriken und die Javascript-Versionierung für die Vergleichbarkeit des Browsers werden hauptsächlich für Sie erledigt. Sie müssen jedoch die Anwendungsarchitektur korrekt verwenden, da sonst die Dinge nicht wie erwartet funktionieren.
quelle
Erstellen Sie model.ts in Ihrem Komponentenverzeichnis wie folgt
export module DataModel { export interface DataObjectName { propertyName: type; } export interface DataObjectAnother { propertyName: type; } }
Importieren Sie dann in Ihrer oben importierten Komponente {DataModel} aus './model'.
export class YourComponent { public DataObject: DataModel.DataObjectName; }
Ihr DataObject sollte alle Eigenschaften von DataObjectName haben.
quelle