【问题标题】:AngularFire2 FirebaseListObservable across multiple (routed) components跨多个(路由)组件的AngularFire2 FirebaseListObservable
【发布时间】:2017-05-14 04:13:16
【问题描述】:

我正在尝试使用 Angular2/Firebase/AngularFire 为我们的帆船俱乐部建立一个社交平台。第一个模块是允许用户通过几个条件(过滤器)搜索俱乐部成员,最多大约 10 个左右。 这本身就意味着我必须四处寻找一种技术来克服 Firebase 中缺乏查询功能的问题。 我创建了一个组件来管理过滤器,使用一个子路由组件来保存成功过滤的成员列表,然后最终创建一个单击处理程序,然后路由到成员配置文件本身。 过滤器组件是这样的: HTML 模板包含多个对所有过滤器选择的单选,例如:性别。单击时,会触发 onFilter 方法。

过滤器组件

<div class="radio">
  <label>
    <input type="radio" name="genderRadios" id="genderRadioM" value="genderMale" (click)="onFilter('crewGender', 'M')">
            Male
  </label>
</div>

这就是 onFilter 方法

constructor(private crewService: CrewService) {}

onFilter(myType, myParam) {
    this.crewFilter = this.crewService.updateFilter(myType, myParam);
}

调用“crewService”服务以使用新值更新过滤器数组。

这是处理此问题的crewService的摘录。

Firebase 服务处理程序 (CrewService)

updateFilter(myType, myParam){
  this.crewFilter[myType] = myParam;
  return this.crewFilter;
}

您可以看到,crewFilter 数组仅包含所有过滤器的键:值对列表。然后 CrewService 服务实现一个方法,该方法采用过滤器数组并将其用作针对我调用的 AngularFire 列表的过滤器,并最终将其生成为 FireBaseListObservable。

@Injectable()
export class CrewService {
  private crewFilter:any[] = [];
  crews:FirebaseListObservable<any[]>;

  constructor(private af: AngularFire) {}

  getCrews() {
  this.crews = this.af.database.list('/crew').map(items => {
  const filtered = items.filter(item => {
    let match:boolean = true;
    for (let i in this.crewFilter) {
      if(this.crewFilter[i] !== 'A') {
        if (item[i] !== this.crewFilter[i]) match = false;
      }
    }
    return match;
  });
  return filtered;
}) as FirebaseListObservable<any[]>;

到目前为止。超好的。这会根据所有过滤器成功过滤 Firebase 列表(忽略 A)。然后在组件模板中显示列表,我使用标准的 ngFor 循环将它们解析出来。

列表组件

  <div *ngFor="let crew of crews | async; let i = index" class="crewsummary row">

为此的 ts 文件包含:

constructor(private crewService: CrewService) { }

ngOnInit() {
  this.crews = this.crewService.getCrews();
  this.crewFilter = this.crewService.getFilter();
}

这样我就调用了 crewService 来填充本地的“crews”对象。

在此组件中,我还创建了取消过滤器的按钮(A 表示全部,因此单击按钮将过滤器设置为“A”,然后在过滤器中被忽略):

<a *ngIf="crewFilter['crewGender'] == 'M'" class="btn btn-primary" (click)="onFilter('crewGender', 'A')">gender: <b>Male</b> <i class="fa fa-fw fa-times"></i></a>
<a *ngIf="crewFilter['crewGender'] == 'F'" class="btn btn-primary" (click)="onFilter('crewGender', 'A')">gender: <b>Female</b> <i class="fa fa-fw fa-times"></i></a>

再次使用 TS:

onFilter(myType, myParam) {
  this.crewFilter = this.crewService.updateFilter(myType, myParam);
  this.crews = this.crewService.getCrews();
}

因为成员列表是从这个组件生成的,所以当我在列表组件中运行 onFilter() 时,它会正确刷新列表并得到正确的结果。

这就是乐趣的开始!

当我首先在过滤器组件中应用过滤器时,我可以让服务重新运行 crampService.getCrews() 以应用过滤器,但它不会被填充到列表组件中。

我无法找到强制列表组件获悉 CrewService.getCrews() 方法已运行并创建新版本列表的方法。

许多小时搜索和尝试与可观察对象和订阅等相关的事情都失败了,当我应用过滤器时,我无法让列表组件成功“订阅”船员对象中的更改。 (请注意,数据库本身所做的更改会成功传播)

所以我不知道这对任何人是否有意义,是否有一个相当简单的解决方案,或者我是否陷入了困境并需要重新考虑。

感谢任何帮助!

谢谢

托尼

【问题讨论】:

    标签: angular typescript firebase angularfire2


    【解决方案1】:

    如果您要为过滤器使用 observable,您可以编写一个结合了最新数据库列表和最新过滤器的 observable。

    过滤器有一个初始值,所以你可以使用BehaviorSubject,像这样:

    import { BehaviorSubject } from 'rxjs/BehaviorSubject';
    import 'rxjs/add/operator/combineLatest';
    
    @Injectable()
    export class CrewService {
    
      private crewFilter:any[] = [];
      private crewFilterSubject = new BehaviorSubject(this.crewFilter);
    
       constructor(private af: AngularFire) {
         this.crews = this.af.database
          .list('/crew')
          .combineLatest(this.crewFilterSubject, (items, filter) => {
            const filtered = items.filter(item => {
              let match:boolean = true;
              for (let i in filter) {
                if(filter[i] !== 'A') {
                  if (item[i] !== filter[i]) match = false;
                }
              }
              return match;
            });
            return filtered;
          }) as FirebaseListObservable<any[]>;
       }
    
      updateFilter(myType, myParam){
        this.crewFilter[myType] = myParam;
        this.crewFilterSubject.next(this.crewFilter);
        return this.crewFilter;
      }
    
      getCrews() {
        return this.crews;
      }
    

    然后你只需要一个单一的、组合的 observable。所以你可以在构造函数中创建它。

    【讨论】:

    • 天才!真的非常感谢你 !完美运行。进入构造函数也感觉好多了。已将其标记为已接受,您为我节省了很多时间和痛苦,再次感谢您!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-20
    • 2018-06-16
    • 2019-05-26
    • 1970-01-01
    • 2016-09-08
    • 2017-06-06
    相关资源
    最近更新 更多