0

I have a FirebaseListObservable and a BehaviorSubject listening a input filter.

Now I want to merge both guys and return an array filtered with the value from the input to feed the md-table.

I got the exemple from https://material.angular.io/components/table/examples filtering table.

Can anyone help me? Thank you.

Edit:

Now it's working but I'm getting an error when loads the component. After I write something on input field, starts to works fine.

ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

What am I doing wrong?

export class DataSourcePessoas extends DataSource<any> {

  pessoas: FirebaseListObservable<any[]>;

  _filterChange = new BehaviorSubject('');
  get filter(): string { return this._filterChange.value; }
  set filter(filter: string) { this._filterChange.next(filter); }

  dados: any[] = [];

  constructor(private pessoasService: FirebasePessoasService) {
    super();
  }

  connect(): Observable<any> {
    const displayDataChanges = [
      this.pessoas,
      this._filterChange,
    ];

    this.pessoas = this.pessoasService.BuscarPessoas();

    this.pessoas.subscribe(items => {console.log(items); this.dados = items});

    return Observable.merge(...displayDataChanges).map(() => {
      return this.dados.filter(valor => {
        return valor.nome.toLowerCase().indexOf(this.filter.toLowerCase()) !== -1})});

  }

  disconnect() {}
}
Nehal
  • 13,130
  • 4
  • 43
  • 59
Taison Morris
  • 878
  • 1
  • 8
  • 12

2 Answers2

0

Well I want to let you know one thing is that if you update any thing in your firebaseListObservable it will automatically updates your firebase database so if you are going to update your firebaseListObservable just to reflect it on your view not in your database then don't do this. Don't update your firebaseListObservable until and unless you want to reflect the changes on your firebase database also. Hope it helps thanks

//reference Code
$tasks: FirebaseListObservable<Task[]>;
tasks:any[];

$tasks = this.db.list('/users/' + uid);

$tasks.subscribe((todoitems) => {
            console.log('items', todoitems);
            this.tasks = todoitems;
        });
//Now you can easily apply filter on this.tasks.filter(()=>{return});
Usman Hussain
  • 187
  • 1
  • 9
  • Thank you for the advice. How do you suggest to get the list from firebase and use "this.filter" to filter the values and show at my table? – Taison Morris Jul 27 '17 at 12:45
  • @TaisonMorris I have added a simple example code for you hope it helps. – Usman Hussain Jul 27 '17 at 13:02
  • It helped a bit, thanks! But I'm getting this error when loads the component. After I type something in input start to works... ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable. – Taison Morris Jul 27 '17 at 20:53
  • It means when component is loaded your array is empty may be thats the issue. try initializing it with empty array or use safe navigation operator in your template binding. Open this link and move to the green tick answer he stated the issue in detail and its the same issue which you are having. https://stackoverflow.com/questions/42364184/why-we-use-operator-in-template-binding-in-angular-2 – Usman Hussain Jul 28 '17 at 05:49
0

I solved my problem changing the BehaviorSubject to Observable

import {Component, ElementRef, ViewChild, OnInit} from '@angular/core';
import {DataSource} from '@angular/cdk';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/observable/fromEvent';

import { FirebaseListObservable } from 'angularfire2/database';
import { FirebasePessoasService } from './../../firebase/firebase-pessoas.service';


@Component({
  selector: 'app-pessoas',
  templateUrl: './pessoas.component.html',
  styleUrls: ['./pessoas.component.scss']
})
export class PessoasComponent implements OnInit {
  displayedColumns = ['nome', 'nascimento', 'email', 'telefone'];
  dataSource: DataSourcePessoas | null;

  @ViewChild('filter') filter: ElementRef;

  constructor(private pessoasService: FirebasePessoasService) {
  }

  ngOnInit() {
    this.dataSource = new DataSourcePessoas(this.pessoasService);
    this.dataSource.input = Observable.fromEvent(this.filter.nativeElement, 'keyup');

  }

  public rowClick(row) {
    console.log(row); // row click
  }
}

export class DataSourcePessoas extends DataSource<any> {

  pessoas: FirebaseListObservable<any[]>;

  input: Observable<any>;

  dados: any[] = [];

  ultimoValor: string = '';

  constructor(private pessoasService: FirebasePessoasService) {
    super();
  }

  connect(): Observable<any> {
    this.pessoas = this.pessoasService.BuscarPessoas();

    this.pessoas.subscribe(items => {this.dados = items});

    const aaa = this.pessoas.merge(this.input);
    return aaa.map(x => {
      if (x.constructor.name === 'Array' ) {
        return x.filter(valor => {
          return valor.nome.toLowerCase().indexOf(this.ultimoValor.toLowerCase()) !== -1})
      } else {
        this.ultimoValor = x.target.value;
        return this.dados.filter(valor => {
          return valor.nome.toLowerCase().indexOf(x.target.value.toLowerCase()) !== -1});
      }});
  }

  disconnect() {}
}
Taison Morris
  • 878
  • 1
  • 8
  • 12