首页 > 解决方案 > 使用打字稿的角度适配器模式用于反应形式

问题描述

我正在寻找有关如何在 angular6 中使用适配器模式的解决方案。我已经阅读了许多文章或教程,但未能掌握其中的概念。请分享一些对此的见解。简而言之,我使用服务来获取一些数据,我需要在组件中使用它,但是组件中使用的模型与服务的模型不同。我需要对其进行编辑并以预期的格式发送回服务。我怀疑的本质是我们是否需要创建一个接口来处理 http 调用?如果是,我们如何保存数据并在我的适配器类中使用它。由于我提到它提倡的链接将数据模型和视图模型分开,我很困惑。

下面是从服务器返回的 json(assets/mocks/quote.json)

{
    "quote": {
        "quoteId": 123,
        "commenseDate": "12/ 15/2018",
        "quoteType": "Small",
        "count": 10,
        "customerInfo": {
            "customerName": "ABC",
            "address": "xxxx xxx xxx",
            "city": "Philadelphia",
            "state": "Philadelphia ",
            "zip": "xxxxx",
            "county": "PA",
            "phone": "",
            "eligibles": 2,
            "employeeCount": 2
        }

    }
}

在连接到 Web 服务时,我对模型和接口的使用感到困惑。在参考了角度文档后,我知道我们需要使用数据模型的接口并在连接到 Web 服务时使用该类型。所以我创建了一个接口来处理我的数据模型

export interface Quote{
    quoteId: number;
    commenseDate: string;
    count: number;
    quoteType: string;
    customerInfo: CustomerInfo
}
export interface CustomerInfo {
    customerName: string;
    address: string;
    city: string;
    state: string;
    zip: number;
    county: string;
    phone: number;
    eligibles: number;
    employeeCount: number;
}

在我的服务调用中,我使用了这个接口。下面是我的 quote-search-service.ts 文件

export class QuoteSearchListService {

/* ApiService- is just a wrapper class to hold the http logic. This class imports HttpClient and uses its get
  * and post methods
*/
  constructor(private apiService:ApiService) { }

  /** Get a quote item */
  getQuoteItem(quoteId:number):Observable<Quote>{

    return this.apiService.get<Quote>('assets/mocks/quote.json')
    .pipe(map((data) => data));
  }
}

我在组件中使用了响应式表单,并使用了如下所示的表单模型

export class QuoteComponent implements OnInit {

    private form: FormGroup;

    constructor(private router: Router, private fb: FormBuilder, private quoteService: QuoteSearchListService) {
        this.form = this.fb.group({
            customerName: [null, Validators.required]
            address: this.fb.group({
                `enter code here`
                address1: ['', Validators.required],
                address2: ['']
            })
            addressDetails: this.fb.group({
                state: [null, Validators.required],
                city: [null, Validators.required],
                zip: [null, Validators.required]
            }),
            county: [''],
            phone: ['', [Validators.required, Validators.minLength(10)]],

            contact: this.fb.group({
                contactFirstName: [null, Validators.required],
                contactLastName: [null, Validators.required],
            }),
            eligibles: [null, Validators.required],
            empCount: [null, Validators.required],
            fteCount: [null, Validators.required]
        })

    }

    ngOnInit() {
        this.getQuoteItem(this.quoteId);
    }

    getQuoteItem() {
        this.quoteService.getQuoteItem(quoteId).subscribe(response => {
            this.form.setValue(response.quote);
        })
    }

}

我的问题如下:

  1. 如何在这种情况下使用适配器模式,以便我的数据模型和表单模型相互独立?
  2. 除了表单模型之外,我是否需要创建要在我的组件中使用的模型/类。例如,表单模型中的“addressDetails”与数据模型不同。
  3. 从数据模型到表单模型的转换(对于 get 调用)以及反之亦然(对于 post/put 调用)将如何发生。我应该写一个额外的服务来来回转换这个模型吗?

我提到的链接: https ://itnext.io/dont-clone-back-end-models-in-angular-f7a749bdc1b0

https://blog.florimondmanca.com/sumption-apis-in-angular-the-model-adapter-pattern

何时在 TypeScript / Angular2 中使用接口和模型

标签: angulartypescriptangular5angular6typescript1.8

解决方案


在 Javascript 中,没有类型。您的变量在被赋值或对其执行操作时是动态类型的。

在 Typescript 中,您可以键入变量。但是一旦编译完成,类型就会被删除。他们只是在这里强制执行一些行为预编译,并帮助您进行智能感知。

但要回答你:

1 - 表单模型应该依赖于数据模型。如果要编辑信息并将其发送回,它们应该具有相同的结构。

为此,您有两个选项,模板驱动(依赖于您的模型)和反应式(依赖于您所做的实现)表单。在您的情况下,您应该使用模板驱动的方法。

2 - 如果发送的有效负载与接收的有效负载(模型方面)没有区别,那么您不应该有不同的模型。所以不,您不应该创建特定于表单的类或接口。

3 - 它应该是透明的,你不应该做任何事情。


推荐阅读