如何在可观察对象上订阅角度模型中的更改?

时间:2018-12-05 16:25:05

标签: angular rxjs observable

我正在通过http加载项目列表,并使用BehaviorSubject将更新从角度服务流式传输到组件。这些项目的布尔值绑定到一个复选框。

我希望另一个组件使用相同的服务并订阅相同的数据源,但仅显示已检查的项目。当加载初始数据时,下面的代码可以正常工作。但是,如果选中了第一个组件中的复选框,则不会更新第二个组件。

我是否需要在检查时从第一个组件手动更新对象并将其推回观察器中?

Full example on stackblitz here

export class MyService {

    private mySubject = new BehaviorSubject<MyModel[]>([]);

    allObservable: Observable<MyModel[]>  = this.mySubject.asObservable();

    selectedObservable = this.allObservable.pipe(map(result => result.filter(f => f.selected)));

    constructor() {
        this.fundsSubject.next([
          { selected: true },
          { selected: false },
        ]);
    }
}

export class MyModel {

  public selected: boolean = false;

}

4 个答案:

答案 0 :(得分:2)

即使您要对data中的AppComponent进行更改,您的MyService也不知道该更改。因此,它不会将新数据推送给订户。

要知道更改,只需对以下文件进行以下更改:

AppComponent模板:

<ul>
  <li *ngFor="let row of data">
     <input (change)="onChange()" type="checkbox" [(ngModel)]="row.selected"/> {{row.name}} 
    </li>
</ul>
<hr/>
Selected:
<hello></hello>

此香奈儿实际上将收听data中的香奈儿。请注意,(change)处理程序已添加到input标记中。

AppComponent类:

import { Component, OnInit } from '@angular/core';
import { MyService, MyModel } from './service.component';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  data: MyModel[];

  constructor(private myService : MyService){}

  ngOnInit() {
    this.myService.allObservable.subscribe(d => this.data = d);
  }

  onChange() {
    this.myService.setUpdatedData(this.data);
  }

}

此更改将通过在其上调用setUpdatedData将更改传播到服务。

并将此方法添加到MyService

setUpdatedData(data) {
  this.mySubject.next(data);
}

此更改会将更改传播到所有subscribe rs。


这里是Working StackBlitz Sample供您参考。

答案 1 :(得分:1)

项目中有许多事情可以改进,但是基本上您需要通知观察者已经进行了更改,可以通过多种方法来进行。我只是添加了一个“有效”的示例,而没有说这是一个很好的解决方案。

https://stackblitz.com/edit/angular-akfqha

// app.component.html
<input ... (change)="notifyChange()"/>

// app.component.ts
public notifyChange(): void {
    this.myService.updateData(this.data);
}

// service.component.ts (preferable named something.service.ts)
public updateData(newData: MyModel[]): void {
  this.mySubject.next(newData);
}

希望这会有所帮助!

答案 2 :(得分:0)

如果要同时在两个组件中导入服务,则angular为每个组件提供单独的服务实例。考虑在提供者范围内添加服务。

您可以使用注释来做到这一点:

@Injectable({
  providedIn: 'root',
})

查找文档here

答案 3 :(得分:0)

订阅可观察对象时,您只需添加一个管道过滤器并仅接受选中的项目即可。示例:

import { filter } from 'rxjs/operators';
import { BehaviorSubject } from 'rxjs';

let _data: BehaviorSubject<Array<string>> = new BehaviorSubject(['']);

_data.subscribe((data) => console.log(1, data)); // takes all results

_data.pipe(filter((stuff: Array<string>) => stuff.some((item) => item === 'batman'))
).subscribe((result) => console.log(2, result)); // only takes results that pass the check

_data.next(['justice']); // test 1
_data.next(['justice', 'batman']); // test 2