Vraag Hoe declareer ik een modelklasse in mijn Angular 2-component met TypeScript?


Ik ben nieuw bij Angular 2 en TypeScript en ik probeer best practices te volgen.

In plaats van een eenvoudig JavaScript-model ({}) te gebruiken, probeer ik een TypeScript-klasse te maken.

Angular 2 lijkt het echter niet leuk te vinden.

Mijn code is:

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

en ik gebruik het als:

import { testWidget} from "lib/testWidget";

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

Ik krijg een fout van Angular:

UITZONDERING: kan niet alle parameters voor testWidget: (?) Oplossen.

Dus ik dacht: Model is nog niet gedefinieerd ... ik zal het naar de top brengen!

Behalve nu krijg ik de uitzondering:

ORIGINELE UITZONDERING: Geen provider voor Model!

Hoe bereik ik dit ??

Bewerken: Bedankt voor het antwoord. Het bracht me op het juiste pad.

Om dit in de constructor te injecteren, moet ik het toevoegen aan de providers op het onderdeel.

Dit lijkt te werken:

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

43
2017-07-15 14:38


oorsprong


antwoorden:


Ik zou dit proberen:

Splits je model in een apart bestand met de naam model.ts:

export class Model {
    param1: string;
}

Importeer het in uw component. Dit geeft u het extra voordeel dat u het in andere componenten kunt gebruiken:

Import { Model } from './model';

Initialiseren in de component:

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

Open het op de juiste manier in de html:

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

Ik wil aan het antwoord een opmerking toevoegen van @PatMigliaccio omdat het belangrijk is om aan te passen aan de nieuwste tools en technologieën:

Als je gebruikt angular-cli je kan bellen ng g class model en het zal het voor u genereren. model wordt vervangen door welke benaming dan ook.


80
2017-07-15 14:55



Het probleem ligt dat je niet hebt toegevoegd Model naar de bootstrap (waardoor het een singleton wordt), of naar de providers array van uw componentdefinitie:

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

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

En ja, je zou moeten definiëren Model boven de Component. Maar het zou beter zijn om het in zijn eigen dossier te plaatsen.

Maar als u wilt dat het slechts een klasse is waaruit u meerdere exemplaren kunt maken, kunt u het beter gewoon gebruiken 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() {}
}

11
2017-07-15 14:52



In jouw geval heb je een model op dezelfde pagina, maar je hebt het gedeclareerd na je Component-klasse, dus dat moet je gebruiken forwardRef verwijzen naar Class. Doe dit liever niet, altijd hebben model object in een apart bestand.

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

Bovendien moet u de interpolatie wijzigen om naar het juiste object te verwijzen

{{model?.param1}}

Het beste dat je zou moeten doen, is dat je de jouwe kunt hebben Model Class definieer in een ander bestand en importeer het vervolgens als wanneer je het nodig hebt door te doen. Hebben ook export voordat je klasse naam, zodat je het kunt importeren.

import { Model } from './model';

5
2017-07-15 14:49



mijn code is

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

en de html gaat als volgt:

<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
2018-01-24 02:54



U kunt de hoekige cli gebruiken zoals de opmerkingen in het antwoord van @ brendon suggereren.

Misschien wilt u ook proberen:

ng g class modelsDirectoy/modelName --type=model

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

Houd in gedachten: ng g class  ! ==  ng g c
U kunt echter gebruiken ng g cl als snelkoppeling afhankelijk van uw versie van angular-cli.


0
2018-04-19 17:22



Ik realiseer me dat dit een wat oudere vraag is, maar ik wilde u erop wijzen dat u de modelvariabele verkeerd aan uw testwidikeklasse hebt toegevoegd. Als u een modelvariabele nodig hebt, zou u niet moeten proberen deze door te geven via de componentconstructor. U bent alleen bedoeld om op die manier diensten of andere soorten injectables door te geven. Als u uw testwidget in een andere component installeert en een modelobject moet doorgeven, raad ik u aan de hoekige kern OnInit en invoer / uitvoer-ontwerppatronen te gebruiken.

Uw code zou bijvoorbeeld er ongeveer zo uit moeten zien:

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

Een klasse die in essentie slechts een struct / model is, mag niet worden geïnjecteerd, omdat dit betekent dat u slechts één gedeelde instantie van die klasse binnen de reikwijdte van de klasse kunt hebben. In dit geval betekent dit dat elke keer dat testWidget wordt geïnstantieerd, door de afhankelijkheidinjector één exemplaar van het model wordt gemaakt. Als het op moduleniveau zou worden aangeboden, zou u slechts één exemplaar gedeeld hebben met alle componenten en services binnen die module.

In plaats daarvan zou u standaard object-georiënteerde praktijken moeten volgen en een privé-modelvariabele moeten maken als onderdeel van de klasse, en als u informatie in dat model moet doorgeven wanneer u de instantie start, moet dit worden afgehandeld door een service (injecteerbaar) van de oudermodule. Dit is hoe de injectie van zowel afhankelijkheid als communicatie bedoeld is om in een hoek uitgevoerd te worden.

Ook, zoals sommige van de andere vermeld, moet u uw modelklassen in een apart bestand declareren en de klasse importeren.

Ik zou sterk aanbevelen terug te gaan naar de referentie van de hoekdocumentatie en de basispagina's van de verschillende annotaties en klassentypen te bekijken: https://angular.io/guide/architecture

U moet bijzondere aandacht besteden aan de secties over modules, componenten en services / afhankelijkheidsinjectie, omdat deze essentieel zijn voor een beter begrip van hoe u Angular op een architectonisch niveau kunt gebruiken. Angular is een zeer architectuurrijke taal omdat het zo hoog is. Scheiding van zorgen, afhankelijkheidsinjectiefabrieken en javascriptversies voor browservergelijkbaarheid worden voornamelijk voor u afgehandeld, maar u moet hun applicatie-architectuur correct gebruiken of u zult merken dat de dingen niet werken zoals u verwacht.


0
2018-04-23 16:46