繁体   English   中英

如何使用 TypeScript 在我的 Angular 2 组件中声明模型类?

[英]How do I declare a model class in my Angular 2 component using TypeScript?

我是 Angular 2 和 TypeScript 的新手,我正在尝试遵循最佳实践。

我没有使用简单的 JavaScript 模型 ({ }),而是尝试创建一个 TypeScript 类。

然而,Angular 2 似乎并不喜欢它。

我的代码是:

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

我将它用作:

import { testWidget} from "lib/testWidget";

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

我从 Angular 收到一个错误:

例外:无法解析 testWidget 的所有参数:(?)。

所以我想,模型还没有定义......我会把它移到顶部!

除了现在我得到了例外:

原始例外:模型没有提供者!

我如何实现这个??

编辑:感谢大家的回答。 它使我走上了正确的道路。

为了将它注入到构造函数中,我需要将它添加到组件的提供者中。

这似乎有效:

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

我会试试这个:

将您的模型拆分为一个名为model.ts的单独文件:

export class Model {
    param1: string;
}

将其导入到您的组件中。 这将为您提供能够在其他组件中使用它的额外好处:

Import { Model } from './model';

在组件中初始化:

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

在 html 中适当地访问它:

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

我想在答案中添加@PatMigliaccio的评论,因为适应最新的工具和技术很重要:

如果您使用angular-cli您可以调用ng g class model ,它会为您生成它。 模型被替换为您想要的任何命名。

问题在于您没有将Model添加到bootstrap (这将使其成为单例)或组件定义的providers数组:

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

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

是的,您应该在Component之上定义Model 但最好是把它放在他自己的档案里。

但是,如果您希望它只是一个可以从中创建多个实例的类,则最好只使用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() {}
}
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();
      }
  }
}

|| 对于非常复杂的数据对象到不存在的默认数据,可以变得非常有用。

. .

在您的 component.ts 或 service.ts 文件中,您可以将响应数据反序列化到模型中:

// 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));

在您的情况下,您在同一页面上有模型,但是您在 Component 类之后声明了它,因此您需要使用forwardRef来引用Class 不喜欢这样做,始终将model对象放在单独的文件中。

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

此外,您必须更改视图插值以引用正确的对象

{{model?.param1}}

您应该做的更好的事情是,您可以将Model类定义在不同的文件中,然后在需要时将其导入。 在类名之前也有export ,以便您可以导入它。

import { Model } from './model';

我的代码是

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

和 html 是这样的:

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

您可以使用 angular-cli 作为@brendon 回答中的评论所建议的。

您可能还想尝试:

ng g class modelsDirectoy/modelName --type=model

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

记住: ng g class !== ng gc
但是,您可以使用ng g cl作为快捷方式,具体取决于您的 angular-cli 版本。

我意识到这是一个较旧的问题,但我只是想指出您错误地将模型变量添加到测试小部件类中。 如果你需要一个模型变量,你不应该试图通过组件构造函数传递它。 您仅打算以这种方式传递服务或其他类型的可注射对象。 如果您在另一个组件内实例化您的测试小部件并需要将模型对象作为传递,我建议使用 angular 核心 OnInit 和输入/输出设计模式。

例如,您的代码应该看起来像这样:

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

不应注入本质上只是结构/模型的类,因为这意味着您只能在提供的范围内拥有该类的单个共享实例。 在这种情况下,这意味着每次 testWidget 实例化时,依赖注入器都会创建一个 Model 实例。 如果它是在模块级别提供的,那么在该模块内的所有组件和服务之间将只共享一个实例。

相反,您应该遵循标准的面向对象实践并创建一个私有模型变量作为类的一部分,并且如果您需要在实例化实例时将信息传递到该模型中,则应由提供的服务(可注入)处理父模块。 这就是依赖注入和通信旨在以角度执行的方式。

此外,正如其他一些人提到的,您应该在单独的文件中声明您的模型类并导入该类。

我强烈建议返回 angular 文档参考并查看各种注释和类类型的基础页面: https : //angular.io/guide/architecture

您应该特别注意关于模块、组件和服务/依赖注入的部分,因为这些对于理解如何在架构级别使用 Angular 至关重要。 Angular 是一种非常注重架构的语言,因为它的级别非常高。 关注点分离、依赖注入工厂和用于浏览器可比性的 javascript 版本控制主要是为您处理的,但是您必须正确使用它们的应用程序架构,否则您会发现事情不像您期望的那样工作。

在您的组件目录中创建 model.ts,如下所示

export module DataModel {
       export interface DataObjectName {
         propertyName: type;
        }
       export interface DataObjectAnother {
         propertyName: type;
        }
    }

然后在上面的组件导入中,从 './model' 导入 {DataModel};

export class YourComponent {
   public DataObject: DataModel.DataObjectName;
}

您的 DataObject 应该具有 DataObjectName 中的所有属性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM