Closed jalalat closed 7 years ago
+1 , Need help too..
@jalalat @ayazhussein Can you explain what exactly do you need?
Start with creating the Meteor subscription to the data, and then expose the cursor result as Observable
, and you Component
will inject the data as service.
You can also expose events if you want to create loading/spinner (example isSubscriptionReady
).
If you wan't to use it within services, it simply the same idea:
import { Injectable } from "@angular/core";
import { MeteorObservable } from "meteor-rxjs";
import { Observable } from "rxjs";
@Injectable()
class MyService {
private _isSubscriptionReady: boolean = false;
private _subscriptionHandler;
constructor() {
}
initSubscription(): void {
if (!this._subscriptionHandler) {
this._subscriptionHandler = MeteorObservable.subscribe("myData").subscribe(() => {
this._isSubscriptionReady = true;
});
}
}
getData(selector, options): Observable<any> {
return MyCollection.find(selector, options);
}
disposeSubscription(): void {
if (this._subscriptionHandler) {
this._subscriptionHandler.unsubscribe();
this._subscriptionHandler = undefined;
}
}
get isSubscriptionReady() {
return this._isSubscriptionReady;
}
}
Am I missing something? Is there other logic you trying to achieve?
that is what I wanted to achieve, but I can't get the correct result here
get isPartiesSubReady() : boolean {
return this._isPartiesSubReady;
}
always returns a false value when I call it in my component
ngOnInit() {
this.partyService.subscribeParties();
console.log(this.partyService.isPartiesSubReady);
this.partyService.getParties().subscribe(parties => {
console.log(this.partyService._isPartiesSubReady);
this.parties = parties;
});
console.log(this.partyService.isPartiesSubReady);
}
It depends when do you call it - if you call it inside ngOnInit
, it might not be ready yet.
Make sure that your subscription ready changes the _isPartiesSubReady
first, and then I recommend to use this directly on the view, in order to know that something changes.
Also, you can expose Observable
for you readiness of the data, and next
it when the data is ready, then using it in your Component
.
Thanks @dotansimha your example is working perfectly. Initially i faced the same issue @ayazhussein mentioned and i was not sure where to subscribe for subscription. I created a subject to pass on the data to component whenever subscription is ready.
in my service
private _isSubscriptionReadySubject: Subject <Observable<Notification[]>> = new Subject<Observable<Notification[]>>();
initSubscription(terms): void {
if (!this._notificationSubHandler) {
this._notificationSubHandler = MeteorObservable.subscribe(terms.viewName, terms).subscribe(() => {
this._isSubscriptionReadySubject.next(this.getData(terms));
});
}
}
getData(terms): Observable<Notification[]> {
let parameters: Parameters = notificationQueryConstructor(terms);
return Notifications.find(parameters.selector, parameters.options);
}
and in my component:
let terms = {
userId: this.user._id,
viewName: 'notifications',
sort: { updatedAt: -1 }
};
this.notificationService.initSubscription(terms);
this.notificationService.isSubscriptionReady().subscribe((data) => {
this.notifications = data.debounce(() => Observable.interval(50)).zone();
});
Hi @jalalat ,
I tried to use your code, but I can't display my data. I have verified and my Minimongo is synchronised.
My service :
private _isSubscriptionReadySubject: Subject <Observable<Instruction[]>> =
new Subject<Observable<Instruction[]>>();
public subscribe(options): void {
if (!this._subscriptionHandler) {
this._subscriptionHandler = MeteorObservable.subscribe('instructions', options)
.subscribe(() => {
this._isSubscriptionReady = true;
this._isSubscriptionReadySubject.next(this.getData({}, options));
});
}
}
public getData(selector, options): Observable<Instruction[]> {
return Instructions.find(selector, options);
}
My component :
public instructions$: Observable<Instruction[]>;
ngOnInit() {
const options = {
sort: {
title: -1
}
};
this.instructionService.subscribe(options);
this.instructionService.isSubscriptionReady().subscribe((data) => {
this.instructions$ = data.debounce(() => Observable.interval(50)).zone();
});
}
My view :
<ul>
<li *ngFor="let item of instructions$ | async">{{ item.title }}</li>
</ul>
Any idea ?
Hi @samy-59
My this.notificationService.isSubscriptionReady() returns subject and not a boolean.
isSubscriptionReady(): Subject <Observable<Notification[]>> {
return this._isSubscriptionReadySubject;
}
I do not have any boolean to indicate if subscription is ready. Rather i am using the Subject and subscribing to it in my component.
This is an old discussion, but since I struggled with this as well, I will post my solutions here. I put as much of the Meteor-specific code in data services, so I won't have to change much in components when would decide to move away from Meteor.
My collection:
import { MongoObservable } from "meteor-rxjs";
import {Demo} from "../models/demo.model";
export const Demos = new MongoObservable.Collection<Demo>('demos');
My service:
import {Injectable, OnDestroy} from '@angular/core';
import {MeteorObservable, ObservableCursor} from 'meteor-rxjs';
import {Demo} from '../../../../both/models/demo.model';
import {Demos} from '../../../../both/collections/demos';
import {Subscription} from 'rxjs/Subscription';
@Injectable()
export class DemoDataService implements OnDestroy {
private demoSubscription: Subscription;
private demoDataSubscription: Subscription;
public data: ObservableCursor<Demo>;
constructor() {
this.demoSubscription = MeteorObservable.subscribe<any>('demos').subscribe(() => {
this.demoDataSubscription = MeteorObservable.autorun().subscribe(() => {
this.data = Demos.find();
});
});
}
ngOnDestroy() {
this.demoSubscription.unsubscribe();
this.demoDataSubscription.unsubscribe();
}
}
My component:
import {Component} from '@angular/core';
import { DemoDataService } from "./demo-data.service";
import template from "./demo.component.html";
import style from "./demo.component.scss";
import {ObservableCursor} from 'meteor-rxjs';
import {Demo} from '../../../../both/models/demo.model';
@Component({
selector: "demo",
template,
styles: [ style ]
})
export class DemoComponent {
constructor(private demoDataService: DemoDataService) {
}
get demoData(): ObservableCursor<Demo> {
return this.demoDataService.data;
}
}
and the components template:
<ul>
<li *ngFor="let item of demoData | async">
{{item.name}} {{item.age}}
</li>
</ul>
Hi @barbatus
Can you please suggest how it is possible to use this package within services. I tried to use it but got no results.
When i tried to call subscribeNotifications(userId) i get this.notifications undefined in my Component. I even tried to wrap the service call in MeteorObservable.autorun() and ngZone.run(); no results.