-1

I am trying to run a crud project in Angular but the data in the table is not showing due to this error:

InvalidPipeArgument: '[object Object], [object Object]' for pipe 'AsyncPipe'

The corresponding line is number 31 in the file named student-list.component.ts. I tried to delete async but it doesn't fix anything. Thank you all.

student.service.ts

import { Injectable } from '@angular/core';  
import { HttpClient } from '@angular/common/http';  
import { Observable } from 'rxjs';  
  
@Injectable({  
  providedIn: 'root'  
})  
  
export class StudentService {  
  
  private baseUrl = 'http://localhost:8080/api/';  
  
  constructor(private http:HttpClient) { }  
  
  getStudentList(): Observable<any> {  
    return this.http.get(`${this.baseUrl}`+'students-list');  
  }  
  
  createStudent(student: object): Observable<object> {  
    return this.http.post(`${this.baseUrl}`+'save-student', student);  
  }  
  
  deleteStudent(id: number): Observable<any> {  
    return this.http.delete(`${this.baseUrl}/delete-student/${id}`, { responseType: 'text' });  
  }  
  
  getStudent(id: number): Observable<Object> {  
    return this.http.get(`${this.baseUrl}/student/${id}`);  
  }  
  
  updateStudent(id: number, value: any): Observable<Object> {  
    return this.http.post(`${this.baseUrl}/update-student/${id}`, value);  
  }  
    
}  

add-student.component.ts

import { Component, OnInit } from '@angular/core';  
import { StudentService } from '../student.service';  
import {FormControl,FormGroup,Validators} from '@angular/forms';  
import { Student } from '../student';  
@Component({  
  selector: 'app-add-student',  
  templateUrl: './add-student.component.html',  
  styleUrls: ['./add-student.component.css']  
})  
export class AddStudentComponent implements OnInit {  
  
  constructor(private studentservice:StudentService) { }  
  
  student : Student=new Student();  
  submitted = false;  
  
  ngOnInit() {  
    this.submitted=false;  
  }  
  
  studentsaveform=new FormGroup({  
    student_name:new FormControl('' , [Validators.required , Validators.minLength(5) ] ),  
    student_email:new FormControl('',[Validators.required,Validators.email]),  
    student_branch:new FormControl()  
  });  
  
  saveStudent(saveStudent){  
    this.student=new Student();     
    this.student.student_name=this.StudentName.value;  
    this.student.student_email=this.StudentEmail.value;  
    this.student.student_branch=this.StudentBranch.value;  
    this.submitted = true;  
    this.save();  
  }  
  
    
  
  save() {  
    this.studentservice.createStudent(this.student)  
      .subscribe(data => console.log(data), error => console.log(error));  
    this.student = new Student();  
  }  
  
  get StudentName(){  
    return this.studentsaveform.get('student_name');  
  }  
  
  get StudentEmail(){  
    return this.studentsaveform.get('student_email');  
  }  
  
  get StudentBranch(){  
    return this.studentsaveform.get('student_branch');  
  }  
  
  addStudentForm(){  
    this.submitted=false;  
    this.studentsaveform.reset();  
  }  
}  

add-student.component.html

<h3>Create Student</h3>  
<div class="row">  
  <div class="col-sm-4"></div>  
  <div class="col-sm-4" >  
    <div [hidden]="submitted" style="width: 400px;">  
      <form [formGroup]="studentsaveform" #savestudent (ngSubmit)="saveStudent(saveStudent)">  
          <div class="form-group">  
              <label for="name">Student Name</label>  
              <input type="text" class="form-control"  formControlName="student_name" data-toggle="tooltip"   
                 data-placement="right" title="Enter Student Name" >  
              <div class="alert alert-danger" *ngIf = "(StudentName.touched) && (StudentName.invalid)"   
                style="margin-top: 5px;">  
                  <span *ngIf="StudentName.errors.required">Student Name is Required</span>  
                    <span *ngIf = "StudentName.errors.minlength">   
                        MinLength Error   
                    </span>                     
                </div>  
          </div>  
    
          <div class="form-group">  
              <label for="name">Student Email</label>  
              <input type="text" class="form-control" formControlName="student_email"   
                data-toggle="tooltip" data-placement="right" title="Enter Student Email">  
                <div class="alert alert-danger" *ngIf = "(StudentEmail.touched) && (StudentEmail.invalid)"   
                style="margin-top: 5px;">  
                  <span *ngIf="StudentEmail.errors.required">Student Email is Required</span>  
                    <span *ngIf = "StudentEmail.errors.email">   
                        Invalid Email Format   
                    </span>                     
                </div>  
          </div>  
    
          <div class="form-group">  
              <label for="branch">Student Branch</label>  
                <select class="form-control" formControlName="student_branch" data-toggle="tooltip"   
                      data-placement="right" title="Select Student Branch">  
                    <option value="null">--Select Branch--</option>  
                  <option value="B-Tech">B-Tech</option>  
                  <option value="BCA">BCA</option>  
                  <option value="MCA">MCA</option>  
                  <option value="M-Tech">M-Tech</option>  
                </select>  
          </div>  
    
          <button type="submit" class="btn btn-success">Submit</button>  
      </form>  
  </div>  
  </div>  
  <div class="col-sm-4"></div>  
</div>  
<div class="row">  
  <div class="col-sm-4"></div>  
  <div class="col-sm-4">  
      <div [hidden]="!submitted">  
         <h4>Student Added SuccessFully!</h4>  
         <button (click)="addStudentForm()" class='btn btn-primary'>Add More Student</button>  
      </div>        
  </div>  
  <div class="col-sm-4"></div>  
</div>  

student-list.component.ts

import { Component, OnInit } from '@angular/core';  
import { StudentService } from '../student.service';  
import { Student } from '../student';  
import { Observable,Subject } from "rxjs";  
  
import {FormControl,FormGroup,Validators} from '@angular/forms';  
  
@Component({  
  selector: 'app-student-list',  
  templateUrl: './student-list.component.html',  
  styleUrls: ['./student-list.component.css']  
})  
export class StudentListComponent implements OnInit {  
  
 constructor(private studentservice:StudentService) { }  
  
  studentsArray: any[] = [];  
  dtOptions: DataTables.Settings = {};  
  dtTrigger: Subject<any>= new Subject();  
  
  students: Observable<Student[]>;  
  student : Student=new Student();  
  deleteMessage=false;  
  studentlist:any;  
  isupdated = false;      
   
  
  ngOnInit() {  
    this.isupdated=false;  
    this.dtOptions = {  
      pageLength: 6,  
      stateSave:true,  
      lengthMenu:[[6, 16, 20, -1], [6, 16, 20, "All"]],  
      processing: true  
    };     
    this.studentservice.getStudentList().subscribe(data =>{  
    this.students =data;  
    this.dtTrigger.next();  
    })  
  }  
    
  deleteStudent(id: number) {  
    this.studentservice.deleteStudent(id)  
      .subscribe(  
        data => {  
          console.log(data);  
          this.deleteMessage=true;  
          this.studentservice.getStudentList().subscribe(data =>{  
            this.students =data  
            })  
        },  
        error => console.log(error));  
  }  
  
  updateStudent(id: number){  
    this.studentservice.getStudent(id)  
      .subscribe(  
        data => {  
          this.studentlist=data             
        },  
        error => console.log(error));  
  }  
  
  studentupdateform=new FormGroup({  
    student_id:new FormControl(),  
    student_name:new FormControl(),  
    student_email:new FormControl(),  
    student_branch:new FormControl()  
  });  
  
  updateStu(updstu){  
    this.student=new Student();   
   this.student.student_id=this.StudentId.value;  
   this.student.student_name=this.StudentName.value;  
   this.student.student_email=this.StudentEmail.value;  
   this.student.student_branch=this.StudentBranch.value;  
   console.log(this.StudentBranch.value);  
     
  
   this.studentservice.updateStudent(this.student.student_id,this.student).subscribe(  
    data => {       
      this.isupdated=true;  
      this.studentservice.getStudentList().subscribe(data =>{  
        this.students =data  
        })  
    },  
    error => console.log(error));  
  }  
  
  get StudentName(){  
    return this.studentupdateform.get('student_name');  
  }  
  
  get StudentEmail(){  
    return this.studentupdateform.get('student_email');  
  }  
  
  get StudentBranch(){  
    return this.studentupdateform.get('student_branch');  
  }  
  
  get StudentId(){  
    return this.studentupdateform.get('student_id');  
  }  
  
  changeisUpdate(){  
    this.isupdated=false;  
  }  
}  

student-list.component.html file

<div class="panel panel-default">  
  <div class="panel-heading">  
      <h1 style="text-align: center">Students</h1><br>  
      <div class="row" [hidden]="!deleteMessage">  
             
                <div class="col-sm-4"></div>  
                <div class="col-sm-4">  
                        <div class="alert alert-info alert-dismissible">  
                                <button type="button" class="close" data-dismiss="alert">×</button>  
                                <strong>Student Data Deleted</strong>  
                        </div>  
                </div>  
                <div class="col-sm-4"></div>  
        </div>             
    </div>  
  
    
  <div class="panel-body">  
      <table  class="table table-hover table-sm" datatable [dtOptions]="dtOptions"  
      [dtTrigger]="dtTrigger"  >  
          <thead class="thead-light">  
              <tr>  
                  <th>Student Name</th>  
                  <th>Student Email</th>  
                  <th>Student Branch</th>  
                  <th>Action</th>  
                    
              </tr>  
          </thead>  
          <tbody>  
               <tr *ngFor="let student of students | async ">  //<------- HERE
                  <td>{{student.student_name}}</td>  
                  <td>{{student.student_email}}</td>  
                  <td>{{student.student_branch}}</td>  
                  <td><button (click)="deleteStudent(student.student_id)" class='btn btn-primary'><i class="fa fa-futboll-0">Delete</i></button>   
                    <button (click)="updateStudent(student.student_id)" class='btn btn-info'  
                    data-toggle="modal" data-target="#myModal">Update</button>  
                  </td>  
                </tr>   
          </tbody><br>  
      </table>  
  </div>  
</div>   
  
<div class="modal" id="myModal">  
        <div class="modal-dialog">  
          <div class="modal-content">  
                <form [formGroup]="studentupdateform" #updstu (ngSubmit)="updateStu(updstu)">  
            <!-- Modal Header -->  
            <div class="modal-header">  
              <h4 class="modal-title" style="text-align: center">Update Student</h4>  
                
            </div>  
              
            <!-- Modal body -->  
            <div class="modal-body" *ngFor="let student of studentlist " >  
                <div [hidden]="isupdated">  
  
                    <input type="hidden" class="form-control"  formControlName="student_id" [(ngModel)]="student.student_id">  
                            <div class="form-group">  
                                <label for="name">Student Name</label>  
                                <input type="text" class="form-control"  formControlName="student_name" [(ngModel)]="student.student_name"  >  
                            </div>  
                      
                            <div class="form-group">  
                                <label for="name">Student Email</label>  
                                <input type="text" class="form-control" formControlName="student_email" [(ngModel)]="student.student_email">  
                            </div>  
                      
                            <div class="form-group">  
                                <label for="name">Student Branch</label>  
                                  <select class="form-control" formControlName="student_branch" required>                                     
                                    <option value="B-Tech" [selected]="'B-Tech' == student.student_branch">B-Tech</option>  
                                    <option value="BCA" [selected]="'BCA' == student.student_branch">BCA</option>  
                                    <option value="MCA" [selected]="'MCA' == student.student_branch" >MCA</option>  
                                    <option value="M-Tech" [selected]="'M-Tech' == student.student_branch">M-Tech</option>  
                                  </select>                                 
                            </div>                     
                  </div>    
                  <div [hidden]="!isupdated">  
                      <h4>Student Detail Updated!</h4>  
                  </div>          
                      
            </div>  
              
            <!-- Modal footer -->  
            <div class="modal-footer" >  
              <button type="submit" class="btn btn-success" [hidden]="isupdated">Update</button>  
              <button type="button" class="btn btn-danger" data-dismiss="modal" (click)="changeisUpdate()">Close</button>  
            </div>  
              
        </form>  
          </div>  
        </div>  
      </div>  

2
  • students is the response from your subscription. You dont need async in your *ngFor. If you remove async what error are you getting if any? Commented Mar 30, 2021 at 19:01
  • this.studentservice.getStudentList().subscribe(data =>{ this.students =data This code is wrong because students is observable and data is not observable. Commented Mar 30, 2021 at 20:40

3 Answers 3

1

subscribed data is not Observable, so you need not use async in template

this.studentservice.getStudentList().subscribe(data =>{  
    this.students = data //data is not Observable 
})  

You need get like that if you want to use asyncPipe:

this.studentservice.getStudentList().subscribe(data =>{  
    this.students = of(data) // please do import {of} from 'rxjs';  
})

And I'm not sure what data you are sending through api calling, but since you are getting [Object, Object], please use JSON.parse, and if you didnt pass JSON format as well, then use JSON.stringify before doing parse like that: JSON.parse(JSON.stringify(data))

Sign up to request clarification or add additional context in comments.

Comments

1

The problem is this code in student-list.component.ts:

this.studentservice.getStudentList().subscribe(data =>{  
  this.students =data;
  this.dtTrigger.next();
})

this.students is an Observable<Student[]> and this.studentservice.getStudentList() returns an Observable<any> (could be better if it returned Observable<Student[]>). So you should do:

this.students = this.studentservice.getStudentList();

That way you would be asigning the observable from the service to your attribute this.students. Then, in the template the async pipe subscribes to the Observable and the ngFor directive loops over the resulting list of students. I don't know what this.dtTrigger.next(); is used for, but after my proposed change, you can achieve the same thing using a RxJS operator:

this.students = this.studentservice.getStudentList().pipe(
  tap(() => {
    this.dtTrigger.next();
  }));

2 Comments

Yes... so when you have an observable, you can use the async pipe in the html, and that way angular handles the subscription for you, so you don't have to worry about subscribing (and unsubscribing by the way), and the code in your controller is cleaner. If you choose the other approach (subscribing to the observable in the controller), remember to unsubscribe to avoid memory leaks, many people forget this. If you didn't know about it, you can read more information in: medium.com/angular-in-depth/…
As you've seen in this post, when you're dealing with observables, you have 2 options: subscribing in the controller or subscribing in the template (using the async pipe). In my experience, subscribing in the controller creates problems in many cases and makes the code in the controller more complex. For example, in some cases you won't see your data updated in the page when you are updating it inside the Observable.subscribe or when you subscribe to valueChanges and you won't know why. I try to avoid all that and consistently use the async pipe instead.
1

Variable Students in file student-list.component.ts must be of type Student[] not Observable<Student[]> because gets its value after subscribing. You should also remove the async pipe.

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.