Utilizing a custom class to perform an HTTP POST request in Angular/TypeScript by implementing the `toString()` method

When working with Angular Reactive forms, I encountered an issue while sending the form.value data to an asp.net web-api. The code snippet includes a custom class called len, which emulates a simplified version of a TimeSpan.

Here is an example of my request:

{
  "id": "a7b06cf9-36a5-4c7a-99e5-8b9661469329",
  "minCapacity": 5,
  "maxCapacity": 10,
  "len": {
    "Days": 0,
    "Hours": 2,
    "Minutes": 0
  },
}

The default behavior of .NET TimeSpan necessitates an input format like this:

string.Format("{0}.{1}:{2}:{3}", len.Days, len.Hours, len.Minutes, len.Seconds)

Otherwise, the variable len registers as null.

To address this, I created an override method toString() for my custom TimeSpan class. However, even after utilizing the HTTP class in my Typescript code, the object persists in JSON format.

Despite scouring through Stack Overflow and Google, I have not been able to find a solution yet. Any guidance on how to handle this at the client side would be highly appreciated.

component.ts

saveItem(model: Room) {
    let selected = this.selected;
    this.roomService.createUpdateRoom(model).subscribe(
        response => {
            Helpers.setLoading(false);
            var result = response as ServiceResult<any>;
            if (result.hasError) {
                this.toaster.error(result.message, 'Error');
            }
            else {
                alert('ok');
                this.viewForm();
            }
        },
        error => {
            this.toaster.error(error.message, 'Error');
        });
}

service.ts

createUpdateRoom(request) {
    return this.post('api/v1.0/room/createupdate', true, request);
}

base.service.ts

post(apiAddress: string, isAuthorizeRequest: boolean, parameter: any): Observable<any> {
        return this.intercept(this.injector.get(AuthHttp).post(this.baseUrl + apiAddress, parameter).map(
            (response) => {
                let data = response.json();
                if (data) {
                    httpSuccess = data;
                }
                return httpSuccess;
            }
        ));
    }

timespan.ts

export class TimeSpan {
day: number = 0;
hour: number = 0;
minute: number = 0;

toTimeString(): string {
    return this.hour +':' + this.minute;
}

toString = (): string => {

    return this.day + ':' + this.toTimeString() + ':00';
}
}

room.ts

export class Room {
    id: string;
    minCapacity: number;
    maxCapacity: number;
    len: TimeSpan;
}

Answer №1

Encountering a familiar issue, I found that discrepancies between the form-model and data-model for a particular property caused problems. To address this, I implemented pre-processing and post-processing procedures to ensure smooth conversion between the two models. While not perfect, establishing this as a consistent pattern made it more manageable in the long run.

Answer №2

Angular reactive forms utilize form group value as either a plain object or an array.

Many developers transitioning from a C# or Java background may have misconceptions about how TypeScript types function within the language. Although the syntax may appear similar, it's important to understand that TypeScript is essentially JavaScript (ES.Next) with added type checking capabilities. These types only impact compile-time checks and do not alter the runtime output, except for certain cases like decorator metadata.

Assigning model: Room does not instantiate model as an instance of the Room class. Instead, the Room class serves as an interface, ensuring that the model object adheres to the structure defined by the Room interface. Type checking will pass if TypeScript recognizes model as a plain object with properties matching those specified in the Room interface, or even if model is of type any. The concept of type assertions follows a similar logic.

To create a model hierarchy consisting of actual class instances such as Room and TimeSpan, these classes need to be instantiated properly. This can be achieved by constructing classes with the necessary properties:

export class TimeSpan {
  ...
  constructor(plainObj: ITimeSpan) {
    this.day = plainObj.day;
    ...
  }
}

export class Room {
  ...
  constructor(plainObj: IRoom) {
    this.len = new TimeSpan(plainObj.len);
    ...
  }
}

Here, ITimeSpan and IRoom represent interfaces containing only properties, excluding methods, from TimeSpan and Room.

Instances of Room can then be created when needed:

saveItem(plainModel: IRoom) {
  const model = new Room(plainModel);
  ...
}

Unless there are specific requirements for maintaining separate instances of Room and TimeSpan, aside from potential custom functionality like a specialized toString method, they may be deemed redundant. Processing of plainModel: IRoom properties, such as converting date strings, can be handled during form submission, possibly within a dedicated processModel method.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In ReactJS, the way to submit a form using OnChange is by utilizing the

Is there a way to submit a form using Onchange without a button? I need to fire the form but can't insert routes as it's a component for multiple clients. My project is built using react hook forms. const handleChange = (e: any) => { c ...

Prisma Date and Time Formatting Challenge

Exploring Nest Js and prisma led me to the need to store DateTime data in my database based on my timezone preferences. joining DateTime @db.Timestamptz(5) ` I found that using @db.Timestamptz resolved my timezone storage issue, but upon retriev ...

Issues arising with utilizing Github for hosting Angular applications

After developing a site with Angular, everything was running smoothly on my local host. However, when I decided to host the site on GitHub, two errors appeared. You can access my site through this link: Here is a screenshot of the errors encountered [1]: ...

In Angular 2, is one-way data binding truly one-way for objects that are passed?

Essentially, passing an object (rather than a primitive) to a component's @input one-way data binding creates a two-way data binding. Any modifications to "bar" within my-component will automatically update the parent component's bar property. W ...

What is causing this error? The length of this line is 118 characters, which exceeds the maximum allowed limit of 80 characters for max-len

I am encountering issues while attempting to upload my function to Firebase, specifically receiving two errors as follows: 39:1 error This line has a length of 123. Maximum allowed is 80 max-len 39:111 warning 'context' is defined but ...

What is the process for incorporating custom parameters into Angular 5 DataTables?

Currently, I am tackling a project that involves Angular5 and PHP as the backend. However, I have hit a roadblock at this stage of development. Below is the snippet of code causing me trouble: this.dtOptions = { pagingType: 'full_numbers', p ...

Creating an Overlay using a ScrollStrategy in a declarative way

In Short; Can you explain how to utilize a scroll strategy when creating a CdkConnectedOverlay in a declarative manner? Details; The CdkConnectedOverlay is designed as a Directive for simplifying the creation of Overlays through a declarative approach. I ...

Ways to eliminate the white background gap between pages on ionic

While developing an app using Ionic, I encountered a strange issue. Everything runs smoothly on a browser, but when testing the app on an Android 5 device, I noticed a white background appearing between pages. The app loads correctly with the custom splas ...

Tackling the white-source security problem in npm libraries

A security advisory from White-source has identified high vulnerability issues with certain libraries used in your repository, specifically with yargs-parser: 1. build-angular-0.13.8.tgz (Root Library) node-sass-4.11.0.tgz sass-graph-2.2 ...

How can I create an instance of a connected component in a Typescript React project?

This particular project consists of distinct components that are not closely related and should be shown side by side. As a result, I aim to configure the application in a way that allows each major component to query the Redux store independently. While t ...

Is there a way to set the submitted variable to true when the form group is submitted, then revert it to false when the user makes changes to the form?

With just one FormGroup, I ensure that when a user submits the form with errors the 'submitted' variable is set to true, displaying the errors. However, my challenge now is how to reset this variable to false when the user makes any changes after ...

Click on the div in Ionic 2 to send a variable

<div class="copkutusu" (click)="kanalsil(kanalid,deneme)" #kanalid id={{ver.channelid}} #deneme id={{ver.channelapikey}}></div> I am requesting kanalid.id and deneme.id in my .ts file. Even though they are the same variable names, they repres ...

Updating the position of an element in HTML is not possible

For my webpage, I am attempting to adjust the position of all images that are displayed. Despite trying to change the position of a single image using the DOM method, I have run into a problem where the position does not update as expected. Although the co ...

Utilizing the drag-and-drop feature within a virtual machine's clarity tree

I am currently working on an Angular application that utilizes the Clarity framework. Within this application, we have implemented a Tree component to showcase a list of items, which is functioning properly. However, we are interested in enabling the abili ...

Angular2 Service Failing to Return Expected Value

It's frustrating that my services are not functioning properly. Despite spending the last two days scouring Stack Overflow for solutions, I haven't been able to find a solution that matches my specific issue. Here is a snippet of my Service.ts c ...

React.js: You cannot call this expression. The type 'never' does not have any call signatures

Could someone help me troubleshoot the error I'm encountering with useStyles? It seems to be related to Typescript. Here's the line causing the issue: const classes = useStyles(); import React from "react"; import { makeStyles } from & ...

Mistake in Resource URL for BreezeJS using C# WebAPI with OData

My project setup involves using BreezeJS/Angular/WebAPI(OData) to make GET calls like this: breeze.EntityQuery .from(resource) .using(manager) .execute() .then(function (data) { deferred.resolve(da ...

Unable to extend baseclass in component class in Angular 4

I am a beginner in Angular and I am attempting to extend a base class with a component class. Here is what the base class looks like: export class QuestionBase<T>{ value?: T; key?: string; label?: string; required?: boolean; order?: number ...

Unable to perform action on Angular 4 data table page. The NGX Store and effect are not functioning properly

Every time I click on the "go to page" button, it redirects me back to page 1. I recently switched to Angular 4, which is quite new to me since I started with Angular 1 a while ago. The strange thing is that the console.log in the page component is loggin ...

Utilizing dependency injection within an Angular 1 TypeScript application

Seeking assistance with integrating angular-jwt with typescript in my angular1 project. The angular-jwt package was installed using the following command: typings install dt~angular-jwt --global The package is located in typings>globals>angular-jwt ...