简体   繁体   English

BehaviorSubject 更改未反映在 UI 上的对象数组中的 1 个属性

[英]BehaviorSubject change 1 property in array of objects not reflecting on UI

I have the following code, this is just a simple select one and select all.我有以下代码,这只是一个简单的选择一个并全选。 The problem is if I click select all, then I unclick one item, this still works fine, the select all checkbox is unchecked automatically and the single item is also unchecked.问题是如果我单击全选,然后我取消单击一个项目,这仍然可以正常工作,全选复选框自动取消选中,单个项目也未选中。

Next, click select all again but the frontend checkbox doesn't display the previously unselected item checkbox as checked even if the select property is already set to true.接下来,再次单击全选,但即使选择属性已设置为 true,前端复选框也不会将先前未选中的项目复选框显示为选中状态。

Any help is appreciated.任何帮助表示赞赏。

Here is my TS code:这是我的 TS 代码:

//This is located in my model.ts
export class SomeClass{
  id: number = 0; 
  selected: boolean = false;
}

//component code

original$: BehaviorSubject<SomeClass[]> = new BehaviorSubject<SomeClass[]>([]);
selected$: BehaviorSubject<SomeClass[]> = new BehaviorSubject<SomeClass[]>([]);
selectAllCheck:Boolean = false;

selectAll(event){        
    this.selectedPlans$ = new BehaviorSubject<SomeClass[]>([]);
    if(event.target.checked)
    {
      this.selectAllCheck = true;         
      for (var i = 0; i < this.original$.value.length; i++) 
      {      
        //this is correctly set to true but checkbox UI remains unchecked
        this.original$.value[i].selected = true;
      }              
      this.selected$.next([...this.original$.value]); 
    }
    else{
      this.selectAllCheck = false;
      for (var i = 0; i < this.original$.value.length; i++) {
        this.original$.value[i].selected = false;
      }      
    }    
  }

selectOne(event, item) {
    const checked = event.target.checked;
    let list = this.selected$.value;
    if (checked) {
      list.push(item);
    }
    else {      
    
      this.selectAllCheck = false;
      _.remove(list, x => x.id == item.id);
      
    }
    if(list.length == this.original$.value.length)
    {
      this.selectAllCheck = true;
    }
    this.selected$.next(list);
  }

Here is my html code:这是我的html代码:

<input id="select All" type="checkbox" (change)="selectAll($event)"[checked]="selectAllCheck">

 <tr *ngFor="let x of original$ | async; let index = index">                  
         <input id="{{ index }}" type="checkbox" [checked]="x.selected"
                      (change)="selectOne($event, x)" />
  </tr>



Your issue is because you didnt call .next() on your this.selected$ BehaviorSubject.您的问题是因为您没有在this.selected$ BehaviorSubject 上调用.next() async pipe subscribes to your BehaviorSubject and returns the latest value it has emitted. async管道订阅您的 BehaviorSubject 并返回它发出的最新值。 And due to you didnt emit any - changing property in the array was not tracked.并且由于您没有发出任何 - 数组中的更改属性没有被跟踪。

Here is a working version of your code.这是您的代码的工作版本。 Also a bit cleared out.也有点清空了。

import { Component } from "@angular/core";
import { BehaviorSubject } from "rxjs";
import { map } from "rxjs/operators";

export class SomeClass {
  id: number = 0;
  selected: boolean = false;
}

const data: SomeClass[] = [
  { id: 1, selected: false },
  { id: 2, selected: false },
  { id: 3, selected: false },
  { id: 4, selected: false },
  { id: 5, selected: false }
];

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  original$ = new BehaviorSubject<SomeClass[]>(data);
  selected$ = this.original$
    .asObservable()
    .pipe(map((x) => x.filter((item) => item.selected)));
  selectAllCheck: boolean = false;

  selectAll(event) {
    this.selectAllCheck = event.target.checked;
    this.original$.value.forEach((x) => (x.selected = this.selectAllCheck));
    this.original$.next([...this.original$.value]);
  }

  selectOne(event, item) {
    item.selected = event.target.checked;
    this.original$.next([...this.original$.value]);
    this.selectAllCheck = this.original$.value.every((x) => x.selected);
  }
}
<div>
  <div>
    <p>Original$</p>
    <input
      id="select All"
      type="checkbox"
      (change)="selectAll($event)"
      [checked]="selectAllCheck"
    />
    <span>Check all</span>

    <tr *ngFor="let x of original$ | async; let index = index">
      <input
        id="{{ index }}"
        type="checkbox"
        [checked]="x.selected"
        (change)="selectOne($event, x)"
      />
      <span>{{x.id}}</span>
    </tr>
  </div>

  <div>
    <p>Selected$</p>

    <tr *ngFor="let x of selected$ | async; let index = index">
      <span>{{x.id}}</span>
    </tr>
  </div>
</div>

编辑winter-lake-nuighh

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM