Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FirebaseObjectObservable after using a switchMap #1008

Closed
fxck opened this issue May 28, 2017 · 5 comments
Closed

FirebaseObjectObservable after using a switchMap #1008

fxck opened this issue May 28, 2017 · 5 comments

Comments

@fxck
Copy link

fxck commented May 28, 2017

When I do this

  key$ = this._activatedRoute.params.pluck('key');
  item$: FirebaseObjectObservable<Client> = this.key$.switchMap(
    (key) => this._db.object(`/client/${key}`)
  );

item$ is not gonna be FirebaseObjectObservable anymore, it's gonna be a AnonymousSubject, without any of the Firebase methods (set() etc.).

It was supposedly fixed by #162 / #321 but it still seems to be broken.

I've seen people on SO using list() and query instead of switchMap, but that doesn't seem right, what would be the point of obervable firebase wrapper if you couldn't use observable chains. But maybe I'm just doing something wrong, don't know. But if it's the case, I think it might be worth adding this usecase (id/key from angular' route param) to the docs, unless I'm blind and it's already there.

Related questions / issues:

Version info

Angular: 4.1.3

Firebase: 4.0.0

AngularFire: 4.0.0.rc-1

rxjs: 5.4.0

cc @davideast

@cartant
Copy link
Contributor

cartant commented May 28, 2017

That isn't how switchMap - and RxJS, in general - works. The observable returned by an operator depends upon the observable upon which the operator is called. Said observable can implement lift to return an observable instance of the same type.

The AngularFire2 observables implement lift - see here and here - but that makes no difference in the situation you have described, as the object observable is inside the switchMap. The observable instance returned by switchMap depends upon the key$ observable - not the object observable.

@fxck
Copy link
Author

fxck commented May 28, 2017

I'm trying to wrap my head around it. Does this mean that what I'm trying to do is impossible, or that the source observable should be the Firebase observable?

@cartant
Copy link
Contributor

cartant commented May 29, 2017

In a broad sense, there will be some way of doing what it is that you are trying to do, but it is impossible for the observable returned by the switchMap operator to be an AngularFire2 observable.

Think about it this way. When the snippet of code in your issue runs, you will have two observable instances: key$ and item$. Clearly, you will have those instances even if the key$ has not emitted a value. Until it emits a value, an object observable will not have been created, so it's obvious that item$ cannot be an AngularFire2 observable.

You could arrange things differently by separating switchMap in to a map and a switch - which would give you an observable that emits AngularFire2 object observables when the key changes:

this.key$ = this._activatedRoute.params.pluck('key');
this.object$$ = this.key$.map((key) => this._db.object(`/client/${key}`));
this.item$ = this.object$$.switch();

If you have an observable for a button click you could access the AngularFire2 observable using object$$:

this.removeClick$
  .withLatestFrom(this.object$$)
  .subscribe((event, object$) => object$.remove());

You'd need to manage the unsubscribe, etc., but that should give you the general idea.

Also, if your component is created and torn down with each route change, you could always use the route's snapshot:

constructor(private _route: ActivatedRoute) {}

ngOnInit(): void {
  this.key = this._route.snapshot.params['key'];
  this.object$ = this._db.object(`/client/${this.key}`);
}

@larssn
Copy link
Contributor

larssn commented May 30, 2017

So I've been working a lot with Observables, and I'd advice towards caution against something like this. RxJS is a great technology, but it creates a lot of mental overhead, meaning one has to sometimes spend quite a long time deciphering how certain observable chains work.

The KISS principle still applies.

@jamesdaniels
Copy link
Member

Going to close as not an af2 issue, but feel free to continue to discuss. Convos like this might be better suited for stackoverflow though

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants