Angular 12 - 使用 Observable 在数组中显示数据

Angular 12 - display data in an Array using an Observable

大家好社区,

我的 angular 12 项目目前遇到问题:

我想显示一个名为 todos 的数组,其中包含我所有的对象变量。但是即使我可以在控制台上看到我的对象正在添加到数组中:todos,似乎有问题(可能是我的 observable),因为它们没有显示在 html 页面上。

我有 2 个组件“add-todo”和“todos”以及 1 个服务“todoService”。

这是我的代码:

//todo.service.ts :

 import { Injectable } from '@angular/core';
import {Todo} from '../models/todo.model';
import {Subject} from "rxjs"

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

  todos:Todo[]=[];
  todoSubject=new Subject <Todo[]>()

  constructor() {

    setTimeout(()=>{
    this.todos=[
      {
        firstname:"Youssef"
      },
      {
        firstname:"Yacine"
      },
      {
        firstname:"Ismail"
      },
    ];

    this.emitTodo();
  },3000)
   }

   addTodo(todo:Todo):void{
     this.todos.push(todo);
     this.emitTodo();
     console.log("Dans todoservice :"+this.todos);
   }

   emitTodo():void{
     this.todoSubject.next(this.todos);
   }
}

//todos.component.ts :

 import { Component,OnInit,OnDestroy } from '@angular/core';
import {TodoService} from '../services/todo.service';
import {Todo} from '../models/todo.model';
import {Subscription} from 'rxjs'

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

  todos;
  todoSub;

  constructor(private todoService:TodoService){}

  ngOnInit():void{
    this.todoSub=this.todoService.todoSubject.subscribe(
      (value:Todo[])=>{
        this.todos=value;
        console.log("Dans todo value :"+value);
      },
      (error)=>{
        console.log("Erreur "+error)
      },
      ()=>{
        console.log("Observable complete");
      }
    )
  }

  ngOnDestroy():void{
    this.todoSub.unsubscribe();
  }



}

//todos.component.html :

   <div class="form-group" *ngFor="let todo of todos;">

  {{todo|json}}


</div>
<p>todo works!</p>

//and finally,

//add-todo.component.ts :

import { Component, OnInit } from '@angular/core';
import { Todo } from '../models/todo.model';
import {TodoService} from '../services/todo.service';
import {Router} from '@angular/router';


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

  todo=new Todo();

  constructor(private todoService:TodoService, private router:Router) { }

  ngOnInit(): void {
  }

  onSubmit():void{

    this.todoService.addTodo(this.todo);
    console.log("Dans add-todo :"+this.todo);
    this.router.navigate(["todos"]);
  }

}

add-todo.component.html :

<p>{{todo|json}}</p>

<form #addTodoForm="ngForm" (ngSubmit)="onSubmit()">

  <label for="name">Firstname :</label>
  <input type="text" name="firstname" [(ngModel)]="todo.firstname" required>

  <button type="submit"  class="btn btn-success" [disabled]="addTodoForm.invalid">Add Todo</button>
</form>```

This is what it shows when I "ng serve" the code :

[![todos.component.html][1]][1]

Then I add a new todo :

[![add-todo.component.html][2]][2]

Then it redirects to the todos.component.html again but it doesn't display all the todos like before :

[![todos.component.html][3]][3]


  [1]: https://i.stack.imgur.com/5P1NQ.png
  [2]: https://i.stack.imgur.com/diIDX.png
  [3]: https://i.stack.imgur.com/PgKxE.png

我认为您需要不可变地更改 Angular(或任何库或框架)中的数组和对象,以便进行更改检测。

对象和数组是引用类型,因此它们存储它们的内存位置,并且对它们执行推送不会更改它们的内存位置。

每次您想更改 Angular 中的数组和对象时,请以不可变的方式进行(分配新值以便内存中的位置发生变化并进行更改检测)。 maps 可能不需要,但我添加了它们,因此数组内的对象在内存中也有新位置。

addTodo(todo:Todo):void{
  // this.todos.push(todo);
  this.todos = [...this.todos.map(todo => ({ ...todo })), todo];
  this.emitTodo();
  console.log("Dans todoservice :"+this.todos);
}

emitTodo():void{
  this.todoSubject.next([...this.todos.map(todo => ({ ...todo })]);
}