0

I'm a beginner in Angular trying to learn the ins and outs. I'm uploading a file and making a call to an API which validates the file. In the response is a list of JSON validation errors that come back based on some values of the file.

I'm attempting to loop through these responses and display them to the user, but I'm a bit lost.

I've tried combinations of map/pipe/subscribe and it seems like the subscribe function is working the best for me and is the only way I can see what the values being sent are. But I'm unsure of how to display the actual values instead of [Object, Object].

I'm also trying to learn the best practices so I'm unsure if I am going down the right path here.

Response object

error list expanded

error list expanded too

enter image description here

What should I be doing after my POST code is returned?

this.httpClient.post(this.PartsAPIURL, formData, { headers: headers })
      .subscribe(event => {
        this.submissionResult = event;
        console.log(this.submissionResult);
        //what to do here?
    });

And how do I combine it with the HTML response?

<p>{{submissionResult}}</p>

Here are some of the failed snippets of code I've been trying

Attempt to assign to an array variable

this.httpClient.post(this.PartsAPIURL, formData, { headers: headers })
      .subscribe(event => {
        //fails because the validationErrors and subcategoryErrors are not initialized properly
        this.UploadResponse.validationErrors = event["validation_errors"];
        this.UploadResponse.subcategoryErrors = event["subcategory_errors"];
        console.log(this.UploadResponse.validationErrors);
        console.log(this.UploadResponse.subcategoryErrors);
    });

Doesnt return anything - no console statements at all

this.httpClient.post<PartsUploadResponse>(this.PartsAPIURL, formData, { headers: headers })
      .pipe(
        map(data => {
          console.log(data)
          this.UploadResponse.subcategoryErrors = data['subcategoryErrors'];
          this.UploadResponse.validationErrors = data['validationErrors'];
          console.log(this.UploadResponse);
        }));

Response class

export class PartsUploadResponse {
  public validationErrors: any;
  public subcategoryErrors:any;

}

Thank you for the help!

1

2 Answers 2

1

Let's define your response type so the typescript compiler can show you any mistakes:

type ErrorResponse = {
  subcategory_errors: ErrorList[],
  validation_errors: ErrorList[]
}

type ErrorList = {
  sheet: string,
  errors: string[]
}

We can assign the error lists to local variables like so:

subcategoryErrors: ErrorList[] = [];
validationErrors: ErrorList[] = [];

ngOnInit() {
  this.httpClient.post(this.PartsAPIURL, formData, { headers: headers })
      .subscribe((data: ErrorResponse) => {
        this.subcategoryErrors = data.subcategory_errors;
        this.validationErrors = data.validation_errors;
    });
}

You can use the *ngFor directive to iterate through an array and display html. Use ng-container to encompass multiple html elements without adding an extra div.

<h1>Subcategory Errors></h1>
<ng-container *ngFor="let errorList of subcategoryErrors">
  <h2>{{ errorList.sheet }}</h2>
  <p *ngFor="let error of errorList.errors">{{ error }}</p>
</ng-container>

<h1>Validation Errors></h1>
<ng-container *ngFor="let errorList of validationErrors">
  <h2>{{ errorList.sheet }}</h2>
  <p *ngFor="let error of errorList.errors">{{ error }}</p>
</ng-container>
Sign up to request clarification or add additional context in comments.

3 Comments

I see, thank you @Chris! So this worked and let me get if I have this right. The subscribe((data: ErrorResponse) was what mapped it to the response where it could figure out what subcategory_errors and validation_errors actually were. Then the ErrorList object defined the sheet and error so it knew how to parse. The ngFor is like the loop where it then loops through what we defined.
@user1299379 Nope, the types are just there so you don't make mistakes as a developer. They have no effect on how the code executes. You had it right in the block you labelled "Attempt to assign to an array variable". I'm guessing the compiler was just telling you that you didn't define types for the UploadResponse property. If you were to force the code to compile, it would execute fine.
*ngFor is the shorthand for the ngForOf directive, which duplicates the html for each entry of an iterable. angular.io/api/common/NgForOf
1

First, the code you implemented with pipe/map operators is correct, but pipe/map operators do not call the api at all, you have to subscribe the observable that is returned from http post method.

Second, after you subscribe the observable that is returned from the http post, you get the object from the API and bind it to the html.

TS code:

this.httpClient.post<any>(this.PartsAPIURL, formData, { headers: headers })
      .subscribe(result=> {
        this.submissionResult = result;
        console.log(this.submissionResult);
        //what to do here?
    });

The 'object object' that is displayed is because you didnt implement the html correcly.
html does not know how to display the all properties within the submissionResult object

In order to display the inner properties in the object, just add elements that should display the inner properties of the object:

Html code:

<p *ngIf="submissionResult">
    <div *ngFor="let validErrors of submissionResult.validationErrors">
      <div *ngFor="let error of validErrors">
         <span>{{error}}</span>
     </div>
   </div>
</p>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.