How to disable view caching in ionic 3 - ionic-framework

We am using ionic 3 with d3js. We have lot of d3.js transitions in each component (which we believe takes lot of memory).
App responds quickly(fast) to navigation and content rendering initially however after navigating 5-10 pages, app gets slower. We see lag in page navigations and content rendering.
We believe this is because of view caching in iconic 3 (not sure if view caching is enabled in iconic 3).
When user clicks on navigation buttons, we push or pop from NavController.
Is there way to disable view caching so that app performance is same irrespective of how many times user navigates between views?
"#ionic/app-scripts": "3.1.9",
"#ionic-native/core": "4.7.0",
Sample code between home page and graph page.
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController) {
console.log('construct again');
}
showMigrationChart() {
this.navCtrl.push(MigrationChart);
}
showColumnChart() {
this.navCtrl.push(ColumnChart);
}
}
#Component({
selector: 'migration-chart',
templateUrl: '../../common/chart.html'
})
export class MigrationChart implements OnInit {
#ViewChild('appChart') private chartContainer: ElementRef;
public chartName = 'Column Chart';
constructor(public navCtrl: NavController) {
console.log('MigrationChart construct again');
}
ngOnInit() {
this.chartName = migrationEngine(this.chartContainer.nativeElement);
}
public onBackClick() {
console.log('getViews length= '+ this.navCtrl.length());
console.log('getViews = ', this.navCtrl.getViews());
this.navCtrl.pop();
}
}

There is no issue with Ionic framework.
On closing of page/component, there were no proper clean up of javascript timers and while loop which was causing app to slow down.
We changed code to do cleanup inside ngOnDestroy and everything work fine now.

Related

Ionic 4 Scroll Position in Service/Guard

I am trying to implement a feature similar to whats available in Facebook i.e. if you have scrolled the news feed, pressing hardware back button takes you to the top of the list.
For this I think believe canDeactivate of Router Guards would be the proper ways.
But I am unable to find a way to check if the page has been scrolled or not.
I have tried window.pageYOffset but this always returns 0, accessing ViewChild within a Guard always returns null.
Can anyone please guide how to achieve this?
There are two approaches for this that should help you.
First, starting with Ionic 4, you can register you back button handler using the Platform features:
https://www.freakyjolly.com/ionic-4-overridden-back-press-event-and-show-exit-confirm-on-application-close/
this.platform.backButton.subscribeWithPriority(999990, () => {
//alert("back pressed");
});
Secondly, you can use more features of Ionic 4 called scrollEvents.
I have explained how to use this feature in other answers:
How to detect if ion-content has a scrollbar?
How to detect scroll reached end in ion-content component of Ionic 4?
ionic 4 - scroll to an x,y coordinate on my webView using typeScript
Hopefully that will get you moving in the right direction.
I think that last answer should solve most of your issue, so something like this:
Freaky Jolly has a tutorial explaining how to scroll to an X/Y coord.
First, you need scrollEvents on the ion-content:
<ion-header>
<ion-toolbar>
<ion-title>
Ion Content Scroll
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [scrollEvents]="true">
<!-- your content in here -->
</ion-content>
In the code you need to use a #ViewChild to get a code reference to the ion-content then you can use its ScrollToPoint() api:
import { Component, ViewChild } from '#angular/core';
import { Platform, IonContent } from '#ionic/angular';
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
// This property will save the callback which we can unsubscribe when we leave this view
public unsubscribeBackEvent: any;
#ViewChild(IonContent) content: IonContent;
constructor(
private platform: Platform
) { }
//Called when view is loaded as ionViewDidLoad() removed from Ionic v4
ngOnInit(){
this.initializeBackButtonCustomHandler();
}
//Called when view is left
ionViewWillLeave() {
// Unregister the custom back button action for this page
this.unsubscribeBackEvent && this.unsubscribeBackEvent();
}
initializeBackButtonCustomHandler(): void {
this.unsubscribeBackEvent = this.platform.backButton.subscribeWithPriority(999999, () => {
this.content.scrollToPoint(0,0,1500);
});
/* here priority 101 will be greater then 100
if we have registerBackButtonAction in app.component.ts */
}
}

How to open a modal component from inside of another modal component without having a circular dependency?

I have two ngx-bootstrap modals created as a standalone components (not with template variables) - Login modal and Register modal. Each of the modals are have separate components which are located in my shared module and can be called from other modules. But the thing is that there is an option these modals to call each other - you can click a button from the login modal which has to bring you the Register modal and vice versa. When I try doing this using the BsModalService I get circular dependency errors since I have imported the login component in the register component and the register component in the login component.
I've tried to put this modal switching logic in a service with the hope that I won't get a circular dependency but it didn't help.
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
import { UserService } from 'src/app/core/services';
import { User } from 'src/app/core';
import { RegisterModalComponent } from '../register-modal/register-modal.component';
#Component({
selector: 'app-login-modal',
templateUrl: './login-modal.component.html',
styleUrls: ['./login-modal.component.css']
})
export class LoginModalComponent implements OnInit {
loginForm: FormGroup = this.fb.group({
// form definition
});
constructor(
public loginModalRef: BsModalRef,
private fb: FormBuilder,
private router: Router,
private user: UserService,
private modalService: BsModalService
) { }
ngOnInit() {
}
onSubmit() {
// form submit code ...
// hide the current modal
this.loginModalRef.hide();
}
openRegisterModal() {
// hide the current modal
this.loginModalRef.hide();
// open the new modal
this.modalService.show(RegisterModalComponent, {
animated: true,
class: 'modal-lg'
});
}
}
I have included only the code from the login modal since the situation on the other side is similar.
Just to mention that as a temporary solution I just made one modal component to serve the purpose as modal and I refactored the login and the register components to be like a regular components so I can include them inside the modal and switch them with ngIf depending on the parameters that I'm calling the modal with.

How to override hardware back button action in Ionic 3?

I want to know which function is called when we click ion-navbar back button by default in ionic 3.
I want to call the same function on hardware back button click.
You can use registerBackButtonAction of Platform Service.
You can override hardware back button action as below inside app.component.ts.
Remember to call registerBackButtonAction after Platform.ready().
import { Platform, App } from 'ionic-angular';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
constructor(public platform: Platform, private app: App) {
this.platform.ready().then(() => {
this.platform.registerBackButtonAction(() => {
let nav = this.app.getActiveNav()
if (nav.canGoBack()) {
// If there are pages in navigation stack go one page back
// You can change this according to your requirement
nav.pop();
} else {
// If there are no pages in navigation stack you can show a message to app user
console.log("You cannot go back");
// Or else you can exit from the app
this.platform.exitApp();
}
});
});
}
}
Hope this will help you.

Ionic Iframe continuesly reload while typing

I created a page with an iframe. The url that the iframe will render has some input fields. When I type something, it reload all the page and I can do nothing.
View
<ion-content no-padding>
<iframe [src]="urlpaste()"></iframe>
</ion-content>
Controller
import { Component } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
my_url: any;
constructor(private sanitize: DomSanitizer) {}
urlpaste(){
this.my_url = "http://example.com/";
return this.sanitize.bypassSecurityTrustResourceUrl(this.my_url);
}
}
It looks like this may have to do with the resize event(s) generated from clicking into the input field, in which case a zoom in happens or the on-screen keyboard pushes the form up. See this:
Ionic 2 Form goes up when keyboard shows

Go back to the previous state

I am trying various solutions from Google but all of them seems to be for Ionic 1 and other versions of Ionic and Angular.
HTML
<button class="edit" (click)="goBackToEnhancementPage();">Edit</button>
On button click I want to goto to the previous state in the history
TypeScript
This is the current state
export class BookingConfirmationPage {
//Some properties
constructor(public navCtrl: NavController, public navParams: NavParams ) {
//Some codes
}
goBackToEnhancementPage(){
canGoBack();
}
}
Previous State
export class BookingEnhancementPage {
//Some code
constructor(public navCtrl: NavController, public navParams: NavParams, public loadingCtrl: LoadingController, private formBuilder: FormBuilder ) {
//This is previous state
}
}
This doesn't work. Please advise what am I doing wrong?
I'm guessing from your question you are trying to use navController to go back to your previous state, aka "back" function.
The way ionic navigation works is like a stack, new pages will be pushed to the top of the stack via "push" via pages will be removed from the top of the stack via "pop"
To go back to your previous state, u can use :
this.navCtrl.pop();
But before that make sure you have push your previous page into navController or you have setRoot your "BookingConfirmationPage" page.
You might want to read up on : https://ionicframework.com/docs/v2/api/navigation/NavController/
If you want your previous details in BookingEnhancementPage to be filled with your user's previously entered data, you might want to use a combination of localstorage and onPageBeforeEnter/onPageWillEnter to populate the fields.