web-dev-qa-db-fra.com

Comment déclarer une classe de modèle dans mon composant Angular 2 à l'aide de TypeScript?

Je suis nouveau dans Angular 2 et TypeScript et j'essaie de suivre les meilleures pratiques.

Au lieu d'utiliser un modèle JavaScript simple ({}), j'essaie de créer une classe TypeScript.

Cependant, Angular 2 ne semble pas l’aimer.

Mon code est:

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;
}

et je l'utilise comme:

import { testWidget} from "lib/testWidget";

@Component({
    selector: "myComponent",
    template: "<testWidget></testWidget>",
    directives: [testWidget]
})

Je reçois une erreur de Angular:

EXCEPTION: Impossible de résoudre tous les paramètres pour testWidget: (?).

Alors j'ai pensé, le modèle n'est pas encore défini ... je vais le déplacer vers le haut!

Sauf que maintenant je reçois l'exception:

EXCEPTION ORIGINALE: Aucun fournisseur pour Model!

Comment puis-je accomplir ceci?

Edit: Merci à tous pour la réponse. Cela m'a conduit sur le bon chemin.

Afin d'injecter cela dans le constructeur, je dois l'ajouter aux fournisseurs du composant. 

Cela semble fonctionner:

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) {}
}
57
Scottie

J'essaierais ceci:

Divisez votre modèle en un fichier séparé appelé model.ts:

export class Model {
    param1: string;
}

Importez-le dans votre composant. Cela vous donnera l'avantage supplémentaire de pouvoir l'utiliser dans d'autres composants:

Import { Model } from './model';

Initialiser dans le composant:

export class testWidget {
   public model: Model;
   constructor(){
       this.model = new Model();
       this.model.param1 = "your string value here";
   }
}

Accédez-y de manière appropriée au format HTML:

@Component({
      selector: "testWidget",
      template: "<div>This is a test and {{model.param1}} is my param.</div>"
})

Je souhaite ajouter à la réponse un commentaire de @PatMigliaccio car il est important de s'adapter aux derniers outils et technologies:

Si vous utilisez angular-cli, vous pouvez appeler ng g class model et le générer à votre place. le modèle est remplacé par le nom de votre choix.

108
Brendon Colburn

Le problème réside dans le fait que vous n'avez pas ajouté Model à la bootstrap (ce qui en fera un singleton), ni au tableau providers de votre définition de composant:

@Component({
    selector: "testWidget",
    template: "<div>This is a test and {{param1}} is my param.</div>",
    providers : [
       Model
    ]
})

export class testWidget {
    constructor(private model: Model) {}
}

Et oui, vous devriez définir Model au-dessus de Component. Mais mieux serait de le mettre dans son propre dossier.

Mais si vous voulez que ce soit juste une classe à partir de laquelle vous pouvez créer plusieurs instances, mieux vaut simplement utiliser 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() {}
}
14
PierreDuc

Dans votre cas, vous rencontrez un modèle sur la même page, mais vous l'avez déclaré après votre classe Component. Vous devez donc utiliser forwardRef pour faire référence à Class. Ne préférez pas faire cela, ayez toujours un objet model dans un fichier séparé.

export class testWidget {
    constructor(@Inject(forwardRef(() => Model)) private service: Model) {}
}

De plus, vous devez changer votre vue d’interpolation pour faire référence au bon objet. 

{{model?.param1}}

La meilleure chose à faire est de pouvoir définir votre classe Model dans un fichier différent, puis de l’importer en tant que de besoin. Ayez également export avant le nom de la classe pour pouvoir l’importer.

import { Model } from './model';
5
Pankaj Parkar

mon code est 

    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 = "";
  }    
  }
}

et le html va comme ceci:

<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>
3
Ahmed Basha
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();
      }
  }
}

Le || peut devenir super utile pour des objets de données très complexes à des données par défaut qui n'existent pas.

. .

Dans votre fichier component.ts ou service.ts, vous pouvez désérialiser les données de réponse dans le modèle:

// 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));
0
Mike Hawes

Je me rends compte que la question est un peu plus ancienne, mais je voulais simplement signaler que vous n’avez pas ajouté correctement la variable de modèle à votre classe de widgets de test. Si vous avez besoin d'une variable de modèle, vous ne devriez pas essayer de la transmettre via le constructeur du composant. Vous n'êtes censé passer que des services ou d'autres types d'injectables de cette manière. Si vous instanciez votre widget de test à l'intérieur d'un autre composant et que vous devez transmettre un objet de modèle en tant que, je vous recommande d'utiliser les modèles de conception OnInit et Input/Output du noyau angulaire.

Par exemple, votre code devrait ressembler à ceci:

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
    }
}

Une classe qui est essentiellement juste une structure/modèle ne doit pas être injectée, car cela signifie que vous ne pouvez avoir qu'une seule instance partagée de cette classe dans la portée qui lui a été fournie. Dans ce cas, cela signifie qu'une seule instance de Model est créée par l'injecteur de dépendance chaque fois que testWidget est instancié. S'il était fourni au niveau du module, vous n'auriez qu'une seule instance partagée entre tous les composants et services au sein de ce module.

Vous devez plutôt suivre les pratiques standard orientées objet et créer une variable de modèle privée dans le cadre de la classe. Si vous devez transmettre des informations à ce modèle lors de l'instanciation de l'instance, cette opération doit être gérée par un service (injectable) fourni par le module parent. C’est ainsi que l’injection de dépendance et la communication sont destinées à être exécutées angulairement.

De plus, comme certains des autres mentionnés, vous devriez déclarer vos classes de modèle dans un fichier séparé et importer la classe.

Je recommanderais vivement de revenir à la référence de documentation angulaire et de passer en revue les pages de base sur les divers annotations et types de classe: https://angular.io/guide/architecture

Vous devriez porter une attention particulière aux sections Modules, Composants et Services/Injection de dépendances, car elles sont essentielles pour comprendre comment utiliser Angular au niveau architectural. Angular est un langage très lourd d’architecture car il est de très haut niveau. La séparation des problèmes, les usines d’injection de dépendances et le contrôle de version Javascript pour la comparabilité du navigateur sont principalement gérées pour vous, mais vous devez utiliser leur architecture d’application correctement ou vous constaterez que les choses ne fonctionnent pas comme prévu.

0
user2904660

Vous pouvez utiliser le paramètre angular-cli comme le suggèrent les commentaires de la réponse de @ brendon.

Vous voudrez peut-être aussi essayer:

ng g class modelsDirectoy/modelName --type=model

/* will create
 src/app/modelsDirectoy
 ├── modelName.model.ts
 ├── ...
 ...
*/

N'oubliez pas: ng g class! == ng g c
Cependant, vous pouvez utiliser ng g cl comme raccourci en fonction de votre version d'angular-cli.

0
xyz