Type 'Observable<Student[]>' is missing the following properties from type 'Student': id, first_name, last_name, English, and 4 more

Viewed 114

I have created two components(table and form) and I want data to be transferred from form to table upon editing. I have written the following code which is throwing the error. Please see to it.console.log(val) is showing the correct value. I want this to be pushed in the data array.I have added both the table component and service

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Student } from '../student';
import { StudentService } from '../student.service';


@Component({
  selector: 'app-table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit {



  data: Student[] = [] 
  single!:Student;
  constructor(public service:StudentService) { }

  getUsers(){
    this.service.getStudents().subscribe((data:any) => {
      this.data=data;
    });
  }

  deleteUsers(id:number){
    this.data = this.service.delete(id,this.data);
  }

  update(id:number){
      this.service.update(id,this.data);
      this.service.currentData.subscribe((val) => {
        console.log(val)
        this.single = val;
        //this.data.push(val)
      });
      this.data.push({
        "English":this.single.English,
        "Hindi":this.single.Hindi,
        "Maths":this.single.Maths,
        "Science":this.single.Science,
        "SST":this.single.SST,
        "first_name":this.single.first_name,
        "last_name":this.single.last_name,
        "id":id
      });
  }


  ngOnInit(): void {
   this.getUsers();
  }

  ngOnDestroy(){
    if(this.service.getStudents().subscribe()){
        this.service.getStudents().subscribe().unsubscribe();
    }
  }

}

Service file

import { Injectable } from '@angular/core';
import { Student } from './student';
import { HttpClient } from '@angular/common/http';
import { throwError } from 'rxjs/internal/observable/throwError';
import { EventEmitter } from 'stream';
import { Observable } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { Router } from '@angular/router';
import { BehaviorSubject } from 'rxjs';



@Injectable({
  providedIn: 'root'
})
export class StudentService {


  users: Student[] = [];
  private data1 = new BehaviorSubject(this.getStudents())
  currentData = this.data1.asObservable();


  private url = '../../assets/MOCK_DATA.json'
  constructor(private http: HttpClient, private router: Router) { 
 }

   getStudents(): Observable<Student[]> {
    return this.http.get<Student[]>(`${this.url}`);
  }

  delete(id: number, data: Student[]): Student[] {
    data = data.filter(item => item.id !== id)
    return data;
  }

  update(id: number, data: Student[]): Student[] {
    data = data.filter(item => item.id != id)
    this.router.navigate(['/form']);
    return data
  }


  setData(data:any) {
    this.data1.next(data);
   } 
}
2 Answers

Well, as far as I can see, you are trying to push Students[] from StudenService.currentData to another Students[], is it intended or something went wrong?

If you want to add all values from StudentService.currentData then you can try change this.data.push(val) to this.data.push(...val)

The problem you are facing seems to be due to this line in the service

private data1 = new BehaviorSubject(this.getStudents())

The type of data1 is BehaviorSubject<Observable<Student[]>> because of this line

this causes the type of currentData to be Observable<Observable<Student[]>> here:

currentData = this.data1.asObservable();

Then in your component when you do:

this.service.currentData.subscribe((val) => {
        console.log(val)
        this.single = val;
        //this.data.push(val)
      });

the type of val is Observable<Student[]>;

Presumably you are getting the error when you do the currently commented line this.data.push(val);

the solution would be to fix the type of the BehaviorSubject in the service. Something like this should do:

private data1 = new BehaviorSubject<Student[]>([]);
...

getStudents(): Observable<Student[]> {
  return this.http.get<Student[]>(`${this.url}`).pipe(
    tap(data => this.data1.next(data))
  );
}

in addition to the above, there is a second issue as pointed by Hephaestus901.

When you do this.data.push(val) you are adding an array as an item of the student array in this.data. something like: [st1, st2, [st3, st4]].

instead do this.data = this.data.concat(val) or as per Hephaestus901's answer

Related