'AngularFireList, property valueChanges() show the error Property 'query' is missing in type 'Observable<{}[]>

I'm having a hard time to figure out this error. Here is my code that I'm building in to make a AuthGuard service:

user.service.ts:

import { Injectable } from '@angular/core';

import { AngularFireDatabase, AngularFireList } from 'angularfire2/database';

import {AppUser} from './models/app.user';
import * as firebase from 'firebase';

@Injectable({
  providedIn: 'root'
})
export class UserService {

  constructor(private db: AngularFireDatabase) { }

  save(user: firebase.User) {
    this.db.object('/users/' + user.uid).update({
      name: user.displayName,
      email: user.email
    });
  }

  get(uid: string): AngularFireList<AppUser> {
    return this.db.list('/users/' + uid).valueChanges();
  }
}

The property .valueChanges() shows me the error:

:>Property 'query' is missing in type 'Observable<{}[]>

I'm also having issues to get the uid:

in AuthGuardService.ts:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/observable';
import 'rxjs/add/operator/switchMap';
import 'rxjs/operator/map';
import { UserService } from './user.service';
import { CanActivate } from '@angular/router';
import { AuthService } from './auth.service';



@Injectable({
  providedIn: 'root'
})
export class AdminAuthGuard implements CanActivate {

  constructor(private auth: AuthService, private userService: UserService) { }

  canActivate (): Observable<boolean> {
    return this.auth.user$
      .switchMap(user => this.userService.get(user.uid).valueChanges())
      .map (appUser => appUser.isAdmin);
  }
}

The error is:

message": "Property 'isAdmin' does not exist on type 'AppUser[]'."

app.user.ts:

export interface AppUser {
    name: string;
    email: string;
    isAdmin: boolean;
}

Can anyone help me to identify how to fix this? Thank you!



Solution 1:[1]

In your service your return type is wrong. You are not returning an AngularFireList<AppUser> you're returning an Observable<AppUser[]>.

In the guard you're passing an array of users to map, so you'd have to check if the first element is an admin instead.

I'm not that familiar with firebase, but it seems a more appropriate alternative in your case to db.list() is db.object() to return a single record:

/* service */
get(uid: string): Observable<AppUser> {
    return this.db.object<AppUser>('/users/' + uid).valueChanges();
}

/* guard */
canActivate (): Observable<boolean> {
    return this.auth.user$
       .switchMap(user => this.userService.get(user.uid))
       .map (appUser => appUser.isAdmin);
}

Solution 2:[2]

I found the answer:

user.service.ts:

import { Injectable } from '@angular/core';

import { AngularFireDatabase, AngularFireObject } from 'angularfire2/database';

import {AppUser} from './models/app.user';
import * as firebase from 'firebase';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UserService {


  constructor(private db: AngularFireDatabase) { }

  save(user: firebase.User) {
    this.db.object('/users/' + user.uid).update({
      name: user.displayName,
      email: user.email
    });
  }

  get(uid: string): AngularFireObject<AppUser> {
      return this.db.object('/users/' + uid);
  }

}

In admin-auth-guard.service.ts:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/observable';
import 'rxjs/add/operator/switchMap';
import 'rxjs/operator/map';
import { UserService } from './user.service';
import { CanActivate } from '@angular/router';
import { AuthService } from './auth.service';




@Injectable({
  providedIn: 'root'
})
export class AdminAuthGuard implements CanActivate {

  constructor(private auth: AuthService, private userService: UserService) { }

   canActivate(): Observable<boolean> {
      return this.auth.user$
      .switchMap(user => this.userService.get(user.uid).valueChanges())
      .map (appUser => appUser.isAdmin);
     }
}

Thanks everybody!

Solution 3:[3]

In get() method use

AngularFireObject<AppUser>

Insted of

Observable<AppUser>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Vini Pineda
Solution 3 smit agravat