Waiting for the HTTP Post response in Angular 2

My Angular2 app is written in TypeScript. I encounter an issue when making a HTTP Post request to create a new record, as the return value from the service does not come back in time to update the DOM with the newly created record. Is there a way to pause processing until the response returns, or to detect changes in my array so I can update the DOM accordingly?

The method in my service looks like this:

public AddComment = (comment: RepackComment): Observable<RepackComment> => {
    var json = JSON.stringify({ comment : comment.Comment, rr_id : comment.RepackId, comment_by : comment.CommentBy });
    return this.http.post(this.commentUrl + 'Add', json, {headers: this.headers})
                    .map((response: Response) => <RepackComment>response.json())
                    .catch(this.handleError);
}

And here is how I handle it in my component method:

saveComment(): void{
    console.log(this.newComment);
    this.repackService.AddComment(this.newComment)
                    .subscribe((data: RepackComment) => this.addedComment = data,
                    error => console.log(error),
                    () => console.log('Finished creating new comment'));

    console.log("added Comment: " + this.addedComment);
    this.comments.push(this.addedComment);
    this.addNewComment = false;
}

Once this.addedComment has been updated with the return value, I want to add it to the this.comments array. Then, I toggle the this.addNewComment flag between displaying input and display fields on the frontend.

Any suggestions are welcome!

EDIT

Here’s the relevant section of my template for handling comments using PrimeNG components:

<p-dataList [value]="comments" [hidden]="addNewComment">
       <header style="height:30px;">
            <button pButton type="button" label="Add Comment" (click)="addComment()" class="actionBtn" style="float:left;width:150px;"></button>
            <span style="margin-left:-105px;font-size:20px;">Comments</span>
       </header>
       <template let-comment>
            <div class="ui-grid ui-grid-responsive ui-fluid" style="font-size:16px;padding:20px;border-bottom:1px solid #D5D5D5;" >
                 <div class="ui-grid-row">
                      <div class="ui-grid-col-12">
                           <div class="ui-grid ui-grid-responsive ui-fluid comment">
                                <div class="ui-grid-row row-div">
                                   <div class="ui-grid-col-3 labelFor">ID: </div>
                                   <div class="ui-grid-col-7 displayFor">{{comment.ID}}</div>
                                </div>
                                <div class="ui-grid-row row-div">
                                   <div class="ui-grid-col-3 labelFor">Comment: </div>
                                   <div class="ui-grid-col-7 displayFor">{{comment.Comment}}</div>
                                </div>
                                <div class="ui-grid-row row-div">
                                   <div class="ui-grid-col-3 labelFor">Author: </div>
                                   <div class="ui-grid-col-7 displayFor">{{comment.CommentBy}}</div>
                                </div>
                             </div>
                         </div>
                     </div>
                  </div>
               </template>
           </p-dataList>
/*INPUT COMPONENTS*/
           <div class="ui-grid ui-grid-responsive ui-fluid" style="font-size:16px;padding:20px;border-bottom:1px solid #D5D5D5;" [hidden]="!addNewComment">
                        <div class="ui-grid-row">
                            <div class="ui-grid-col-12">
                                <div class="ui-grid ui-grid-responsive ui-fluid comment">
                                    <div class="ui-grid-row row-div">
                                        <div class="ui-grid-col-3 labelFor">Comment: </div>
                                        <input type="text" pInputText [(ngModel)]="newComment.Comment" class="displayFor"/>
                                    </div>
                                    <div class="ui-grid-row row-div">
                                        <div class="ui-grid-col-3 labelFor">Author: </div>
                                        <input type="text" pInputText [(ngModel)]="newComment.CommentBy" class="displayFor"/>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <br/>
                        <div class="div-row" style="margin-left:40%;">
                            <button pButton type="button" label="Cancel" (click)="cancelComment()" class="actionBtn" style="width:150px;"></button>
                            <button pButton type="button" label="Save" (click)="saveComment()" class="actionBtn" style="width:150px;"></button>
                        </div>
                    </div>

https://i.sstatic.net/hX5DE.png

Answer №1

It's important to note that Observables work asynchronously, meaning that everything after the .subscribe call will likely be executed before the code inside the .subscribe callback.

To address this issue, make sure to place any code that depends on the results of the subscribe call within its callback function:

saveComment(): void{
    console.log(this.newComment);
    this.repackService.AddComment(this.newComment)
                    .subscribe((data: RepackComment) => {
                        this.addedComment = data;

                        // Add your code here
                        console.log("added Comment: " + this.addedComment);
                        this.comments.push(this.addedComment);
                        this.addNewComment = false;
                    },
                    error => console.log(error),
                    () => console.log('Finished creating new comment'));
}

Additionally, it appears that the object returned from your post call does not match your template. I suggest modifying your AddComment method to align with a constructor for RepackComment like so:

public AddComment = (comment: RepackComment): Observable<RepackComment> => {
    var json = JSON.stringify({ comment : comment.Comment, rr_id : comment.RepackId, comment_by : comment.CommentBy });
    return this.http.post(this.commentUrl + 'Add', json, {headers: this.headers})
                    .map((response: Response) => response.json())
                    .map(res => new RepackComment(res.id, res.comment, res.comment_by))
                    .catch(this.handleError);
}

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

An error occurred while parsing JSON: `Unexpected ending near "ma-sauce-launcher":"*`

After executing the command ">ng new angular-app" on Windows, I came across the following error: npm ERR! Unexpected end of JSON input while parsing near '...ma-sauce-launcher":"*' Package installation failed, please refer to the above error ...

Angular2 Collaborative Module

Hey, I've been wondering about something. So, I have a bunch of components that I want to use in various parts of my application. However, rather than loading all these components right from the start, I'd prefer to load them on demand (lazy load ...

Angular encountering issues with loading external JavaScript files due to the error: ENOENT - indicating that the specified file or directory does

I am attempting to incorporate a bootstrap template into Angular. The template requires some external JavaScript and CSS files that need to be linked. I have placed these files in the assets folder and referenced them in the styles and scripts arrays of an ...

Create a mechanism in the API to ensure that only positive values greater than or equal to 0 are accepted

My goal is to process the API result and filter out any values less than 0. I've attempted to implement this feature, but so far without success: private handleChart(data: Object): void { const series = []; for (const [key, value] of Object.e ...

"Receiving HTML response from an HTTP GET request in Angular 2

Attempting to transmit test data from my node.js server to the front end. router.get('/abc', (req, res) => { return res.json({ test: "success!" }); }); In my service component: private url = "http://localhost:4200/auth/abc"; getTitl ...

Can you explain the meaning and significance of the @Injectable annotation?

Is the use of @Injectable indicating that we are able to inject MyService into other classes, or does it mean that we can inject other classes into MyService? @Injectable({ providedIn: 'root' }) export class MyService { constructor() { } } ...

Make sure to incorporate the .gitignored files that are compiled from typescript when running the `npm install -g

Looking for a way to ignore the JavaScript files compiled from TypeScript in my git repository to make merging, rebasing, and partial commits easier. Here's how I have it set up: tsconfig.json { "compilerOptions": { "outDir": "./dist" ...

Mistakes encountered when compiling TypeScript Definition Files

I am looking to convert my JavaScript files (*.js) to TypeScript files (*.ts) in my ASP.net MVC5 application (not an Asp.net Core app). I am using Visual Studio 2015. After downloading the TypeScript Definition Files into the Scripts\typings\ fol ...

How do you verify an OpenID Connect access token produced by Azure AD v2 in an ASP.NET Core web API?

What is the best way to verify an OpenID Connect Access Token generated by Azure AD (v2) in ASP.NET Core Web API? Here's the situation: I have an Angular 8 Client Application that receives an OpenID Connect access Token post Login. The Client can us ...

Emphasize a Row Based on a Certain Criteria

One of the challenges I am facing is how to emphasize a specific row in a table based on certain conditions. Currently, I am utilizing Jqxgrid and have made some modifications in the front-end to achieve the highlighting effect: TypeScript: carsDataAgain ...

Setting up Identity Server 4 integration with Ionic 2

Currently, I am in the process of setting up Identity Server to function with Ionic 2. I am a little confused about how to set up the Redirect URLs specifically for testing purposes in the browser. Furthermore, I am updating and integrating an OIDC Cordov ...

The issue arises when trying to set the height of the modal body correctly while using ng-bootstrap to open the modal as a separate component

There seems to be an issue with the height not being properly added in the modal body when the modal is opened as a separate component using ng-bootstrap. The problem can be seen in the following link: https://i.sstatic.net/natkn.png https://stackblitz.co ...

Transforming an Observable to a boolean using RXJS

Hey there, I'm currently working on creating a function similar to this: verify(){ return this.http.post(environment.api+'recaptcha/verify',{ token : this.token }).pipe(map(res=>res.json())); } I want to be able to use ...

Issue with Angular Compilation When Importing Library Function into Web Worker

I am facing an issue with a web worker in Angular that used to function properly in the previous versions: /// <reference lib="webworker" /> import { ParseResult } from "papaparse"; import { readCSV } from '@fireflysemantics/ ...

Verify user authentication

My journey with learning Angular 2 has hit a roadblock. I have set up routes in my application as follows: const appRoutes: Routes = [ {path: 'start', component: StartComponent, children:[{path: '' }, { path:&ap ...

The challenge of validating in Typescript and utilizing type inference

I am currently facing an issue with a function that resembles the one provided below (I have created a simplified example for discussion purposes): interface Variable { someMethod: () => void } const validateVariable(variable: Variable | undefined) { ...

Exploring the intricacies of pattern matching with JavaScript visualization

I am currently working on improving my pattern matching function by creating a visualizer for it. To achieve this, I need to slow down the execution of each comparison. My approach involves declaring the i and j variables outside of the function so that I ...

Picture fails to load on Ionic app on the device

Currently, I am utilizing Ionic 3 for my project. The location of the images file is \src\assets\img. This pertains to a basic page implementation. export class BasicPage { items = []; constructor(public nav: NavController ,private adm ...

Evaluate the functionality of a designated button using its unique identifier

Within my HTML file, there is a button that has the following structure: <a class="sub-menu-button" [matMenuTriggerFor]="menu" id ="subMenuBtn" [class.full-opacity]="getNodeResult(node).highlight" [class.highlight]="text.highlight" matTooltip="Search o ...

Setting the default value for ngModel does not receive any information from the model

I am trying to populate a form with default values using the code below: <h3>ِStart Time</h3> <div class="row" > <div class="col"> <label for="startTime">Hour(s) </label> <input type="numb ...