Search code examples
node.jsangularmongodbobservablengfor

NgFor only supports binding to Iterables such as Arrays.Cannot find differ supporting Object


I have came across so many links in the website regarding the same Issue. But I couldn't solve it. I am sorry for asking this type of question again.

In my project, I want to iterate through the tasks and display it. I am getting those tasks from backend.I am able to view the tasks through console, but am unable to view in the webpage, as it giving an error. I tried using 'keyvalue' in the ngFor, but when am using nothing is being displayed.

task.service.ts

get_tasks():Observable<Task>{
    return this.http.get<Task>('http://localhost:3000/tasks/');
  }

  createTask(task:Task){
    console.log(task);
    return this.http.post('http://localhost:3000/tasks/',task);
  }

  deleteTask(id){
    return this.http.delete('http://localhost:3000/tasks/'+id);
  }

  updateTask(task){
    return this.http.put('http://localhost:3000/tasks/'+task.id,task).pipe(map(res=>{
      console.log(res);
      }));
  }

tasks.component.ts

ngOnInit(){
    this.getTasksList();
  }

  getTasksList(){
    this.taskService.get_tasks().subscribe((task:any)=>{
      this.tasksList=task;
      console.log(this.tasksList);
    })

  }

  newTasks(event){
    event.preventDefault();
    var newList={
      _id:this.id,
      title:this.title,
      isDone:false
    }
    this.taskService.createTask(newList).subscribe((task:any)=>{
      this.tasksList.push(task);
      this.title='';
    })

  }

  removeTask(id){
    var tasks=this.tasksList;
    this.taskService.deleteTask(id).subscribe((data)=>{
      for(var i=0;i<tasks.length;i++){
        if(tasks[i]._id=id){
          tasks.splice(i,1);
        }
      }
    })

  }

task.component.html

<div class="tasks">
  <div class="tasks-list" *ngFor="let task of tasksList">
    <div class="col-md-1">
      <input type="checkbox">
    </div>
    <div class="col-md-7">
      {{task.title }}


</div>

Where am doing wrong??Is it with the type?? can anyone please explain where am doing wrong. enter image description here


Solution

  • It appears the backend is returning an object with the array contained in the property called data.

    Option 1: You could either assign it in the controller and not change the template

    Controller

    getTasksList(){
      this.taskService.get_tasks().subscribe((task:any) => {
        this.tasksList = task['data'];
        console.log(this.tasksList);
      });
    }
    

    Template

    <div class="tasks">
      <div class="tasks-list" *ngFor="let task of tasksList">
        <div class="col-md-1">
          <input type="checkbox">
        </div>
        <div class="col-md-7">
          {{ task?.title }}
        </div>
      </div>
    </div>
    

    Option 2: Or not change the controller and access the property in the template

    getTasksList(){
      this.taskService.get_tasks().subscribe((task:any) => {
        this.tasksList = task;
        console.log(this.tasksList);
      });
    }
    

    Template

    <div class="tasks">
      <div class="tasks-list" *ngFor="let task of tasksList?.data">
        <div class="col-md-1">
          <input type="checkbox">
        </div>
        <div class="col-md-7">
          {{ task?.title }}
        </div>
      </div>
    </div>
    

    Option 3: Or if you could adjust the backend, keep the front-end code unchanged and adjust the backend to return the array [{}, {},...] instead of the object {data: [{}, {},...]}.