skip to Main Content

It’s really expensive to transfer whole model from server to client specially when loading lists. The solution is to ignore empty, null or default values which can be refilled in client side. Consider a Customer model like this:

export class Customer {
    customerId: number = 0;
    ncode: string = 'some default text';
    name: string = '';
    age: int = 20;
    isActive: boolean = false;
    birthday: Date | null = null;

    // And much more fields ...
}

We have same model in server side and the server will ignore null and default fields in serialization. For example, this is a customer sent from server:

"{'customerId':1234}"

What happens is that the object created by angular http get, is a Customer with only customerId field! All other fields are undefined.
Is there any solution to fix it globally with no third party library to force angular to value missing fields with their default values?

Update:
Here is the request code:

export class CustomerComponent implements OnInit {
  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    this.http.get<Customer>('/api/getCustomer').subscribe((response) => {
      console.log(response); // {'customerId':12345}
    });
  }
}

Update 2:
As I thought there may be a global solution, I made a simple example. But we have a generic function to handle all api requests, which is generic and returns <T>(<any>response)

public request<T>(api: string, method: string = 'GET', formData: any): Observable<T>{
    return new Observable((observer: Observer<T>) => {
        header = new HttpHeaders({/*...*/});
        this.http.request<T>(new HttpRequest(method, api, JSON.stringify(formData), {headers: header}))
            .subscribe({next: (response) => {
                observer.next(<T>(<any>response)); // <= This line must be changed I think
            }});
    }
}

2

Answers


  1. When you receive the data from the backend you could do the following trick:

    1. Instantiate a new object of the desired class: It will automatically contain your default-values.
    2. Merge the newly created object with the incoming data, using the spread-operator.
    ngOnInit(): void {      
        this.http.get<Customer>('/api/getCustomer').pipe(
            // Instantiate an object with default-values
            // and merge it with the retrieved partial-object:
            map(res =>({ ...new Customer(), ...res } as Customer))
        )
        .subscribe((response) => { console.log(response); });
    }
    
    
    Login or Signup to reply.
  2. Explained

    Using Customer class as type for the http request does not influence the runtime code. Http resonse will not automatically create a new instance of your Customer class and assign the values to it. Types in typescript are just used for development purpose (compiler time) and will not influence the runtime code results. Checkout w3school introduction.

    TypeScript uses compile time type checking. Which means it checks if the specified types match before running the code, not while running the code.

    Solution

    To get a Customer with your defaults you could create a new instance of the Customer which has the static default you have defined and assign only the http resonse values that are set. Something like :

          this.request<Customer>('/api/getCustomer').subscribe((response) => {
            const customer = new Customer();
         
            Object.keys(response).forEach(field => {
                 
                       customer[field] = response[field];
                  
              });
              
              console.log(customer); // response will be a Customer instance 
            });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search