I have an Ionic 2 app. The premise of the app is to take a class. Once a class has been opened the user is marked as taking this class in the remote API.
The flow of data is:
NavController.push(Page, { 'classes': classObjFromApi });
.classes
object passed to it.NavController.popToRoot()
On the root page each class' status is shown ('Not started', 'In progress', 'completed'). At point 5 in the above flow the user is taken back to the root, but this has the data from when it was originally constructed, which shows the class as 'Not started', even though it's 'completed' now.
How can I update the data on the root page from a different page in the stack? I had assumed that popToRoot()
would accept navParams
so I could check for the presence of that data in the root page and use it if it exists or request from the API if not.
I can get around this by re-requesting data from the API on the ionViewDidEnter
method, but that means an API/HTTP request every time the user views this page, even though the app has the data. Seems messy.
I'd rather not use internal storage if I can help it, as it creates a delay when loading the page, as I have to wait for data to be pulled from storage before displaying it.
So my question: what's the best way of doing this? If it is to pass data to the view, how do I do that if popToRoot()
doesn't support nav params?
The best way to do that would be by using Events:
In your root page, subscribe to a custom event, to execute some code every time that event is published:
import { Events } from 'ionic-angular';
constructor(public events: Events) {
events.subscribe('status:updated', (updatedData) => {
// You can use the updatedData to update the view
// ...
});
}
// Clean up the subscription when the page is about to be destroyed
ionViewWillUnload() {
this.events.unsubscribe('status:updated');
}
And publish that event in any other page, when the user changes that data:
import { Events } from 'ionic-angular';
constructor(public events: Events) {}
yourMethod(): void {
// Your custom logic...
// ...
// Now you can publish the event to update the root page (and any other page subscribed to this event)
this.events.publish('status:updated', updatedData);
}
EDIT
Another way to do that, would be by using a shared service, and using a Subject
to publish/subscribe to changes. The result would be pretty similar to Ionic Event's, but in this scenario you'd need to add a shared service and then use it when the data is updated. I'd prefer Ionic Events, but just in case, this is how you could do it:
import { Subject } from 'rxjs/Subject';
@Injectable()
export class MySharedService {
public onDataChange: Subject<any>;
constructor() {
this.onDataChange = new Subject<any>();
}
public publishUpdate(newData): void {
// Send the data to all the subscribers
this.onDataChange.next(newData);
}
}
So now in your root page, subscribe to the changes using the shared service
import { Subscription } from 'rxjs/Subscription';
// ...
private onDataChangeSubscription: Subscription;
constructor(public mySharedService: MySharedService) {
this.onDataChangeSubscription = mySharedService.onDataChange.subscribe(
updatedData => {
// You can use the updatedData to update the view
// ...
});
}
// Clean up the subscription when the page is about to be destroyed
ionViewWillUnload() {
this.onDataChangeSubscription.unsubscribe();
}
And you'd need to use the shared service too when updating the data from any other page:
constructor(public mySharedService: MySharedService) {}
yourMethod(): void {
// Your custom logic...
// ...
// Now you can publish the event to update the root page (and any other page subscribed to this event)
this.mySharedService.publishUpdate(updatedData);
}
This approach may be better if you need to execute some custom logic every time the data is updated, so instead of doing that on each subscriber, you could just do it in the shared service, and broadcast the result...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With