Ionic version:
[x] 4.1.0
Current behavior:
Ionic router run OnInit only first time
Expected behavior:
Run OnInit each time
I have an app with Angular. It is a simple list of items, after clicking on an item opened item details page. Two routes:
const routes: Routes = [
{
path: 'index',
component: IndexComponent
},
{
path: 'item/:id',
component: ItemDetailsComponent
}
];
I use ItemsService -> get/save items.
export class IndexComponent implements OnInit {
public items: Array<Item>;
constructor(private itemsService: ItemsService) {
}
ngOnInit() {
this.itemsService.getItems()
.subscribe(data => this.items = data)
}
}
export class ItemDetailsComponent implements OnInit {
public item: Item;
constructor(private route: ActivatedRoute,
private itemsService: ItemsService) {
}
ngOnInit() {
const id = this.route.snapshot.params['id'];
this.itemsService.getItem(id)
.subscribe(data => this.item = data)
}
}
In Angular application, OnInit lifecycle event working each time when I open these pages.
And it is fine. I should edit an item on ItemDetailsComponent, and after clicking back to IndexComponent I see new information.
I start an Ionic project. Changed router-outlet
to ion-router-outlet
Same structure, same routing.
And now:
IndexComponent OnInit working the only first time. When I back to this page from ItemDetailsComponent - OnInit not rerun. Ionic reuse IndexComponent, But I need a new instance.
ItemDetailsComponent OnInit working the only first time for each item in the items list.
But if I edit an item, return back to IndexComponent, update items handly(click a button, because OnInit not work). And open ItemDetailsComponent again - I see old information because OnInit not firing - this is an old instance.
I tried to delete
{
provide: RouteReuseStrategy,
useClass: IonicRouteStrategy
}
from app.module
But OnInit still not working
https://gyazo.com/6afec1e7936e1254b41009ab942a2d3f
How I can disable this? I need only one component, not stack
If I use custom RouteReuseStrategy I can't use route animations
Just subscribe to the params...
this.route.params
.subscribe((params: Params) => {
console.log(params['id']);
});
@digaus, This is not working, because of an old component in stack,
Hi @traziusbiztest,
Thanks for the issue! I can confirm this is a bug. By default, we cache the component when navigating (whereas a regular Angular component destroys it and re-creates it when going back). We have a fix in the works that should resolve issues where routing isn't working after the first time, params aren't being updated, etc.
Work on the fix is well underway, and I hope to have more info to share soon!
Thanks for using Ionic!
Temporary solution?
How to destroy an old component in stack?
Hi there,
If you are trying to run code every time a particular page enters (or re-enters the view), you can use the ionViewDidEnter
lifecycle hook. This hook is "fired when the component being routed to has animated in": https://ionicframework.com/docs/api/router-outlet
If you are trying to respond to changes in data, you could subscribe to the data via an Observable as @digaus suggested, or you can create an injectable that holds the data. With the injectable, you can write a method that serves up the data you need.
For help on implementing either of these ideas, feel free to post on our forums or our slack.
Thanks!
i totally agree with @liamdebeasi
ngOnInit is only called, when the angular component gets initialised, which is not the case for ionic routing.
the previous pages are cached and only disconnected from the change detection.
The ionic component lifecycle hooks and the angular router events/observables should fulfill your needs.
It is like ionic navigation is working. Maybe it should be better documentated or clearified in the docs.
I also stumbled over this bug. I changed the lifecycle events to the ionic ones which works well on components that are accessed via the router (let's call them pages). But on components that are on this page the ionViewWillLeave
doesn't seem to be called. So the component that is on a page is not notified if the parent component is going into the cache.
Because of this I cannot unsubscribe an observable that I passed to the sub-component.
Hope this makes sense, I'll try to notify the component via an input that is called on ionViewWillLeave
of the parent component.
I also detected the same behavior when I tried to follow the tutorial of Maximilian Schwarzm眉ller @ https://www.youtube.com/watch?v=r2ga-iXS5i4&t=2h57m53s
For me, the tutorial doesn't work anymore when it's about trying to delete positions of the list like in https://www.youtube.com/watch?v=r2ga-iXS5i4&t=3h17m0s and change back to the view which lists all positions.
I tried ionViewDidEnter
and it worked well for me. Is there any better idea?
Same bug here.
Hi, I tried to work around with this by using ionic events.
I had the same problem when a route is initialized but requires re-authentication(when it tries to retrieve data(by ngOnInit) but instead get a 401 error in return because of expired token(verification happens on my backend)) so navigating to login route. After a successful login, navigate back to the previous URL to retrieve the data again. which result to the OnInit never gets called again after initialization.
I tried to use router NavigationEnd but I encountered problems, like it is firing multiple times.
so i decided to use the ionic events.
I just specify the topic on publish(I used the router url as topics) and for every route subscription.
so if an event.subscribe hits the right topic. It can execute a certain function(call ngOnInit again).
https://ionicframework.com/docs/v3/api/util/Events/
hope someone might find this helpful.
sorry its my first time to post comment.
Please work on this issue on priority. Many are facing this issue and will start creating workarounds and/or assume ngOnInit will be loaded once and write some logic. When this behavior changes, it will cause issues in the future.
There should be a way to not cache views at all!
It seems that ngOnInit()
will fire so long as some parameters change. Using ionDidViewEnter(),
doesn't work very well because it fires after the components have been generated, causing errors.
So what I have used, is ugly, but it works. Every time I navigate to a page that I have previously visited, I append a random number (uuid to insure uniqueness) to the parameters. This causes ngOnInit()
to fire every time a page is visited.
No perfect, not pretty, but practical.
5 months still open?
Is this bug has fixed ?
@Tauqeer1 This has been fixed in the newer versions of Ionic.
It's not fixed, still facing this issue
It's not fixed, still facing this issue
@Papabeer04 Which version ? Fresh install or an upgrade using package.json ?
It seems that
ngOnInit()
will fire so long as some parameters change. UsingionDidViewEnter(),
doesn't work very well because it fires after the components have been generated, causing errors.So what I have used, is ugly, but it works. Every time I navigate to a page that I have previously visited, I append a random number (uuid to insure uniqueness) to the parameters. This causes
ngOnInit()
to fire every time a page is visited.No perfect, not pretty, but practical.
I'm getting: ExpressionChangedAfterItHasBeenCheckedError
Can you show an example of how you did it?
It's not fixed, still facing this issue
@Papabeer04 Which version ? Fresh install or an upgrade using package.json ?
5.2.4
My problem remains with a modal, when I open the modal and close it and go to another page. Then go back to the page and open the modal again ionViewWillEneter and ionViewDidEnter don't work.
ionViewWillEnter fixed my normal pages at the moment.
I used ionViewWillEnter() instead of ngOnInit(). It works,
I did some investigations. Hope it helps
Ionic version
@ionic/angular 4.11.1
Actual result
I have 2 pages: Welcome, Login and I just navigate forward, don't have any back navigation.
Scenario 1
Scenario 2
Expected Result
From log I should see 2 lines of log for Login page OnInit event.
Thanks for improving this framework!
Guys. Please don't say I use ionViewWillEnter and it works. What does temporary solution mean for you? What @liamdebeasi suggest is using ionViewWillEnter when "run code every time a particular page enters" and it is acceptable solution for this case only. How about the other cases? You will get temporary solution and use another temporary solution because this temporary solution make.
You might ask why. I will show you how Ionic ionViewWillEnter and Angular ngOnInit different in log. Ionic-Angular already different when it fires component events.
Angular
LoginPageComponent constructor
ngOnInit
ngDoCheck
ngAfterContentInit
ngAfterContentChecked
ngAfterViewInit
ngAfterViewChecked
Ionic-Angular
LoginPageComponent constructor
ngOnInit
ngDoCheck
ngAfterContentInit
ngAfterContentChecked
ngAfterViewInit
ngAfterViewChecked
ngDoCheck
ngAfterContentChecked
ngAfterViewChecked
ngDoCheck
ngAfterContentChecked
ngAfterViewChecked
ionViewWillEnter
ngDoCheck
ngAfterContentChecked
ngAfterViewChecked
ionViewDidEnter
ngDoCheck
ngAfterContentChecked
ngAfterViewChecked
ngDoCheck
ngAfterContentChecked
ngAfterViewChecked
My problem remains with a modal, when I open the modal and close it and go to another page. Then go back to the page and open the modal again ionViewWillEneter and ionViewDidEnter don't work.
ionViewWillEnter fixed my normal pages at the moment.
@Papabeer04 , I'm facing with the same issue just as you wrote. Did you able to fix the issue?
When will ionic team fix this issue? As far as I see it's not a new one...
Dear All,
@traziusbiztest
@liamdebeasi
@Papabeer04
@kamvir
@thinkdj
I have tried all the above suggestions but no luck for me. Please let me know what I need to do as I am also facing same problem.
Why ngOnInit() works only once when I come back to home page the data not displaying. :(
Please help me.
Thanks in advance.
Mozib Khan
For me the problem was actually in my service. I followed the course of Simon Grimm but he makes a mistake.
(Using firebase)
service.ts :
constructor(private afs: AngularFirestore) {
this.ideaCollection = this.afs.collection<Idea>(ideas);
this.ideas = this.ideaCollection.snapshotChanges().pipe(
map(actions => {
return actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return { id, ...data };
});
})
);
}
getIdeas(): Observable<Idea[]> {
return this.ideas;
}
Should be:
constructor(private afs: AngularFirestore) {
this.ideaCollection = this.afs.collection<Idea>('ideas');
}
getIdeas(): Observable<Idea[]> {
return this.ideas = this.ideaCollection.snapshotChanges().pipe(
map(actions => {
return actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return { id, ...data };
});
})
);
}
For me the problem was actually in my service. I followed the course of Simon Grimm but he makes a mistake.
(Using firebase)
service.ts :
constructor(private afs: AngularFirestore) { this.ideaCollection = this.afs.collection<Idea>(ideas); this.ideas = this.ideaCollection.snapshotChanges().pipe( map(actions => { return actions.map(a => { const data = a.payload.doc.data(); const id = a.payload.doc.id; return { id, ...data }; }); }) ); } getIdeas(): Observable<Idea[]> { return this.ideas; }
Should be:
constructor(private afs: AngularFirestore) { this.ideaCollection = this.afs.collection<Idea>('ideas'); } getIdeas(): Observable<Idea[]> { return this.ideas = this.ideaCollection.snapshotChanges().pipe( map(actions => { return actions.map(a => { const data = a.payload.doc.data(); const id = a.payload.doc.id; return { id, ...data }; }); }) ); }
Wow! you are great it works for me.
Thank you so much @Papabeer04
Please get in touch via my skype (chaton_skype)
Thanks,
Mozib
Try this:
constructor(
private zone: NgZone
) {}
this.zone.run(() => {
this.router.navigateByUrl('/login', { skipLocationChange: true });
});
This is happening because ionic router caches pages. If the page is cached only ionViewWillEnter
will be called.
But if a page wasn't cached then ngOnInit
will be called every time
Still facing issue with @ionic/cli version v6.4.1
_ _
(_) ___ _ __ (_) ___
| |/ _ | '_ | |/ __|
| | (_) | | | | | (__
|_|___/|_| |_|_|___| CLI 6.4.1
Any updates ? Ionic 5 still having this issue.
Hi, I tried to work around with this by using ionic events.
I had the same problem when a route is initialized but requires re-authentication(when it tries to retrieve data(by ngOnInit) but instead get a 401 error in return because of expired token(verification happens on my backend)) so navigating to login route. After a successful login, navigate back to the previous URL to retrieve the data again. which result to the OnInit never gets called again after initialization.I tried to use router NavigationEnd but I encountered problems, like it is firing multiple times.
so i decided to use the ionic events.I just specify the topic on publish(I used the router url as topics) and for every route subscription.
so if an event.subscribe hits the right topic. It can execute a certain function(call ngOnInit again).https://ionicframework.com/docs/v3/api/util/Events/
hope someone might find this helpful.
sorry its my first time to post comment.
I had the same problem as @irealyze on Ionic 5
ionic 5 still the problem persist
i also had trouble with this issue (refactored my navigation from tabs to pages thinking these would solve the on init issue), but it seems to be a general issue where a clear workaround/guidance for exists
the current docs of ionic tell how to deal with it:
https://ionicframework.com/docs/angular/lifecycle#how-ionic-handles-the-life-of-a-page
https://ionicframework.com/docs/angular/lifecycle#guidance-for-each-life-cycle-method
guidance says:
Hi @traziusbiztest,
Thanks for the issue! I can confirm this is a bug. By default, we cache the component when navigating (whereas a regular Angular component destroys it and re-creates it when going back). We have a fix in the works that should resolve issues where routing isn't working after the first time, params aren't being updated, etc.
Work on the fix is well underway, and I hope to have more info to share soon!
Thanks for using Ionic!
What's the progress of this issue? Do we have plan to fix it? Or is there an official suggestion how we should handle with it.
Like @kamvir said I used ionViewWillEnter() instead of ngOnInit() and it works.
Most helpful comment
Hi @traziusbiztest,
Thanks for the issue! I can confirm this is a bug. By default, we cache the component when navigating (whereas a regular Angular component destroys it and re-creates it when going back). We have a fix in the works that should resolve issues where routing isn't working after the first time, params aren't being updated, etc.
Work on the fix is well underway, and I hope to have more info to share soon!
Thanks for using Ionic!