angular 中的适配器模式使用打字稿作为反应形式

Adapter pattern in angular using typescript for a reactive form

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

下面是服务器返回的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
        }

    }
}

我对连接到网络服务时模型和接口的使用感到困惑。在参考 angular 文档后,我知道我们需要使用数据模型的接口,并在连接到 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;
}

在我的服务电话中我使用了这个 interface.Below 是我的报价搜索-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. 我是否需要创建 models/classes 以在除表单模型之外的组件中使用。 例如,请参见表单模型中的 'addressDetails' 与数据模型不同。
  3. 如何从数据模型转换为表单模型(对于 get 调用),反之亦然(对于 post/put 调用)。我应该写一个额外的服务来来回转换这个模型吗?

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

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

在Javascript中,没有打字。当你的变量被赋值时,或者当对它们执行操作时,它们是动态类型的。

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

但是要回答你:

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

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

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

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

在我看来,一般来说,form-model 和 data-model 是不同的。所以你需要将表单模型转换为数据模型,反之亦然。

在哪里?如果它是 "simple" 和共同价值,我喜欢在服务中使用。例如我们收到一个字符串格式的日期,我们想要作为日期对象,或者收到一个字符串类型 "London|Madrid" 并且您想转换为数组

service.getList().pipe(map(list=>{
   list.forEach(item=>
      {
        item.date=new Date(item.date); //now "date" is a Date Object
        item.cities=item.cities.split('|');  //now cities is an array of Strings
   }))

嗯,我们在服务中的saveData变成了这样

saveData(data)
{
     data.date=data.date.getFullYear()+"-"+
            ("0"+(data.date.getMonth()+1)).slice(-2)+"-"+
            "0"+(data.date.getDate()).slice(-2)
     data.cities=data.cities.join("|");
     this.httpClient.post("....",data)
}

如果比较复杂,我更愿意在组件中make