Search code examples
angulartypescriptangular5angular6typescript1.8

Adapter pattern in angular using typescript for a reactive form


I am looking for a solution on how to use adapter pattern in angular6. I have read scores of articles or tutorials but failed to grasp the concept of that. Please share some insights on this. In short I use a service to fetch some data, I need to use this in a component but the model used in component is different from that of service. I need to edit it and send back to service in the intended format. Essence of my doubt is do we need to create an interface to handle http calls? If yes how do we hold the data to and use it in my adapter class. Since the links I referred it advocates make data models and view models separate, I am confused.

Below is the json returned from the server(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
        }

    }
}

I am confused over the usage of model and interface while connecting to a webservice. After referring the angular docs I am aware that we need to use interface of our data model and use that type when we connect to a webservice. So I have created an interface to handle my data model

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

In my service call I used this interface.Below is my quote-search-service.ts file

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

I use a reactive form in my component and I use a form model shown below

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

}

My questions are listed below:

  1. How to use adapter pattern in this context so that my data model and form model will be independent of each other?
  2. Do I need to create models/classes to be used in my component other than the form model. See for example 'addressDetails' in the form model is different from the data model.
  3. How will the conversion from data-model to form-model(for get call) and vice versa (for the post/put call) happens. Should I write an extra service to convert this model back and forth?

Links I referred: https://itnext.io/dont-clone-back-end-models-in-angular-f7a749bdc1b0

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

When to use Interface and Model in TypeScript / Angular2


Solution

  • In Javascript, there is no typings. Your variables are dynamically typed when they are assigned a value, or when an operation is performed on them.

    In Typescript, you have the possibility to type your variables. But once the compilation is made, the types are removed. They are just here to enforce some behavior pre-compilation, and to help you with intellisense.

    But to answer you :

    1 - The form model should depend on the data model. If you want to edit the informations and send them back, they should have the same structure.

    For that, you have two options, template-driven (which relies on your model), and reactive (which relies on the implementation you make) forms. In your case, you should use the template-driven approach.

    2 - If the payload sent doesn't differ from the payload received (model-wise), then you should not have different models. So no, you should not create classes or interfaces that are specific to the form.

    3 - It should be transparent, you should not have to do anything.