0

Someone already used ng-table on angular and could figure out how to use it with firebase collecction?

I'm trying to use ng-table (last example) to sort and filter my collection on Angular 10, so I tried to just change the constant in the code to my object and I it did not work. I think I need to convert my object to an array, so I tried this library to do it, and also dont work. Also tried to look for this on stackoverflow and all I find out is others with the same problem.

This is the exact function where I need to do this. COUNTRIES is the array that comes from *countries.ts. The function bellow is on country.service.ts.

  private _search(): Observable<SearchResult> {
    const {sortColumn, sortDirection, pageSize, page, searchTerm} = this._state;

    // 1. sort
    let countries = sort(COUNTRIES, sortColumn, sortDirection);

    // 2. filter
    countries = countries.filter(country => matches(country, searchTerm, this.pipe));
    const total = countries.length;

    // 3. paginate
    countries = countries.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize);
    return of({countries, total});
  }
}

That is what I tried with the lib that found out:

this.items = this.firestore.collection('users').valueChanges();

alert( O2A(this.items) );

But it does not work for me.

Thank's!

6
  • when do you call _search() from your service ? and what do you try to achieve with the O2A method? ValuesChanges already returns an observable containing an array. Commented Oct 26, 2020 at 13:07
  • I got this error: Type 'Observable<User[]>' is missing the following properties from type 'User[]': length, pop, push, concat, and 25 more. Commented Oct 26, 2020 at 13:20
  • You get this because it is an observable that is returned. It is an async object that, when subscribed, emits the data in your collection every times it gets updated (create, update, delete on your firebase collection). You first need to subscribe to it to request the array by doing: this.items.subscribe(res => alert(O2A(res))). Don't forget to unsubscribe once you don't need it, otherwise, you will create a data leak in your app which will be terrible for your app performance. Commented Oct 26, 2020 at 13:26
  • Still got the error. Could you get a complete example of how you solve this and change sample data for a firebase collection on ng-table? Commented Oct 26, 2020 at 13:38
  • Can you edit your question with what you tried to achieve after my comment ? I have no clue on your end goal and your implementation. Your two pieces of code seem unrelated to me. How do they interact with each other ? Commented Oct 26, 2020 at 14:07

1 Answer 1

3

I will take the example you provide to answer.
The minimum requirement for this to work is to slightly adapt the country.service. We have a change in the constructor() and the private _search() method. We will need to replace the COUNTRIES variable that contains the array of data with your array of users (note that you will need to adapt all the code to match your users attributes):

country.service.ts

...
users: User[];

constructor(private pipe: DecimalPipe) {
    this._search$.pipe(
      tap(() => this._loading$.next(true)),
      debounceTime(200),
      switchMap(() => this._search()),
      delay(200),
      tap(() => this._loading$.next(false))
    ).subscribe(result => {
      this._countries$.next(result.users);
      this._total$.next(result.total);
    });
    // this will get your users and start the _search$ above
    this.firestore.collection('users').valueChanges().pipe(take(1)).subscribe(users => {
        this.users = users;
        this._search$.next();
    });
  }
  
  private _search(): Observable<SearchResult> {
    const {sortColumn, sortDirection, pageSize, page, searchTerm} = this._state;

    // 1. sort
    // provide your users (instead of COUNTRIES exemple variable) as a param 
    let users = sort(this.users, sortColumn, sortDirection);

    // 2. filter
    users = users.filter(user => matches(user, searchTerm, this.pipe));
    const total = users.length;

    // 3. paginate
    users = users.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize);
    return of({users, total});
  }
...

Don't forget to rename your variables accordingly (users instead of countries) and your type (User instead of Country) in methods params.

I won't make all the work, since it is too broad, but at least, you get the idea how to initiate the service with your firestore data.

Change also the SearchResult interface, you'll get a compile error otherwise:

interface SearchResult {
  users: User[];
  total: number;
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you very much! Looks like it is the solution for me. But I had a problem with the "take" function, got this errors: Cannot find name 'take'. 89 this.firestore.collection('users').valueChanges().pipe(take(1)).subscribe(users => { ~~~~ src/app/pages/users/item.service.ts:90:9 - error TS2740: Type '{}' is missing the following properties from type 'User[]': length, pop, push, concat, and 26 more.
Take is an rxjs operator. It will take the first emission and complete the observable (you just need a single request to get your data). But you need to import it in order to use it. To do this, put import { take } from 'rxjs/operators'; with the other imports.
Yes, Thank you! I think I'm almost there. I'm only getting now the erro I was getting before. I do import my interface from import {User} from './item'; but still got this error: Type 'unknown[]' is not assignable to type 'User[]'. Type '{}' is missing the following properties from type 'User': id, bio, birthday, createdDate, and 15 more. 90 this.users = users;
I changed the this.firestore.collection('users') by this.firestore.collection<User>('users') and this fix this error, so I put it on console.log and get the erray like you said, but still not load the infos on table
That way returns the results, but it creates one array for each 100 registers. I edit the answer to show whats I get on console

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.