【问题标题】:Angular - Edit a Subject which is a type of ArrayAngular - 编辑作为数组类型的主题
【发布时间】:2021-11-29 11:45:23
【问题描述】:

我正在编写一个管理员可以升级用户权限的应用程序。

在我向服务器发送请求以增加用户的权力之后。我从服务器返回用户列表:

powerUp(id: number) {
return this.http
  .post<Hero[]>(environment.apiUrl + 'heroes/powerUp/' + id, {})
  .pipe(
    map((heroes) => {
      this.currentHeroes.next(hero);
    })
  );

}

这里是主题:

private currentHeroes = new BehaviorSubject<Hero[]>(null);
currentHeroes$ = this.currentHeroes.asObservable();

问题是它不是官方的,因为我只能从服务器返回正在启动的特定用户。

powerUp(id: number) {
    return this.http
      .post<Hero[]>(environment.apiUrl + 'heroes/powerUp/' + id, {})
      .pipe(
        map((hero) => {
          // update the particular hero in the currentHeroes subject
        })
      );
  }

我的问题是如何在没有.next() 的情况下修改 currentHeroes 主题(仅限更新的用户)而不从服务器返回整个列表。

我已尝试关注:

  powerUp(id: number) {
    return this.http
      .post<Hero>(environment.apiUrl + 'heroes/powerUp/' + id, {})
      .pipe(
        map((updatedHero) => {
          this.currentHeroes$.pipe(
                // doesn't enter here
                map((oldHeroes) => {
                  const index = oldHeroes.findIndex((hero) => hero.id === id);
                  oldHeroes[index] = updatedHero;
                })
              );
            })
          );
      }

英雄卡模板

export class HeroCardComponent implements OnInit {
  @Input() hero: Hero;

  constructor(public heroService: HeroService, private toastr: ToastrService) {}

  ngOnInit(): void {}

  powerUp(id: number, name: string) {
    this.heroService.powerUp(id).subscribe(() => {
      this.toastr.success(`${name} was successfully powered up!`);
    });
  }

  delete(id: number, name: string) {
    this.heroService.delete(id).subscribe(() => {
      this.toastr.success(`${name} was successfully deleted`);
    });
  }
}

谁能解释一下我该怎么做?

【问题讨论】:

    标签: angular behaviorsubject


    【解决方案1】:

    您可以替换之前的 currentHeroes$,如果您使用的是 async 管道,它应该可以直接使用。

    如果您的模板如下所示:

    <div *ngFor="let hero of (currentHeroes$ | async)">
      <app-hero-card [hero]="hero"></app-hero-card>
    </div>
    

    您的组件可能如下所示:

    @Component({…})
    export class HeroListComponent {
    
      currentHeroes$: Observable<Hero[]>
      constructor(private heroService: HeroService) {
        this.currentHeroes$ = this.heroService.getHeroes()
      }
    
      powerUp(heroId: string) {
        this.currentHeroes$ = this.heroService.powerUp(heroId).pipe(
          switchMap(updatedHero => {
              return this.currentHeroes$.pipe(
                map(oldHeroes => {
                   const index = oldHeroes.findIndex(hero => hero.id === updatedHero.id)
                   oldHeroes[index]=updatedHero
                   return oldHeroes
                })
              );
          })
         );
      }
    }
    

    现在对魔法进行一些解释:

    1. HeroService.powerUp(heroId) 将返回一个 observable,一旦网络请求完成,它将发出更新后的英雄
    2. 然后我们通过应用来自 RxJS 的 switchMap 管道来转换该 observable。 switchMap 所做的是它允许说;好的,这里发生的任何事情都将由另一个 observable(我们返回的那个)处理
    3. 在返回的 Observable 上,我们只是获取旧的 currentHeroes$ observable 并通过查找它的 id 并更新数组项来替换旧的 hero。最后返回更新后的数组

    额外提示

    如果后端返回更新后的列表或者您可以触发重新获取,代码会少很多

    如果后端返回完整列表

    powerUp(heroId:string) {
      this.currentHeroes$ = this.heroService.powerUp(heroId)
    }
    

    如果您想触发重新提取

    powerUp(heroId:string) {
      this.currentHeroes$ = this.heroService.powerUp(heroId).pipe(
        switchMap(_updatedHero => this.heroService.getHeroes())
      );
    
    }
    

    【讨论】:

    • 非常感谢您的精彩解释!!!!我已经编辑了我的问题,因为我尝试了你的方式,同时根据我的需要稍微修改了它,但不幸的是它没有按预期工作。我想知道你能看看吗?
    • 我认为您缺少作为 map 操作的最后一条语句的 return 语句 oldHeroes。否则返回undefined
    • 很遗憾,这不是问题
    • 那可以分享一下模板吗?
    • 当然可以。但对不起我的无知。你指的是什么模板?
    猜你喜欢
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2011-06-13
    • 2010-11-09
    相关资源
    最近更新 更多