My Ionic application first loads LoginComponent and when user successfully logs in, loads the main TabsComponent view which allows to switch between corresponding child views.
I am trying to make it load standalone LoginComponent without tabbed interface, and that is not working (once switched to TabsComponent, I cannot navigate away from tabbed interface).
I've tried following commands from under one of TabsComponent child views:
this.navCtrl.push(LoginComponent); // Loads as a child view
this.navCtrl.setRoot(LoginComponent); // Loads as a child view
this.navCtrl.popAll(); // Error: navigation stack needs at least one root page
this.navCtrl.popTo(LoginComponent); // Error: navigation stack needs at least one root page
I've went through Ionic documentation many times but I haven't found an answer to this question. What am I missing?
I've solved this by injecting TabsComponent into it's child component, and then calling this.navCtrl.setRoot(LoginComponent); in a function inside TabsComponent:
// Child class of TabsComponent (loaded via tab click)
export class SettingsComponent {
constructor(#Inject(forwardRef(() => TabsComponent)) private tabsComponent: TabsComponent) {
}
logOut(): void {
this.tabsComponent.switchToLoginPage():
}
}
And switchToLoginPage on TabsComponent:
import {Component, forwardRef, Inject} from '#angular/core';
// ...
export class TabsComponent {
constructor(private navCtrl: NavController) {
}
switchToLoginPage(): void {
this.navCtrl.setRoot(LoginComponent);
}
}
Based on this example: How do I inject a parent component into a child component?
If there is a better way I'd love to know about, otherwise hope this solution would help anyone.
Related
Seems like a simple question, but I haven't been able to find a simple answer. Essentially I want to choose which page in the app to start on based on some stored state. I added a GoToAsync call in the AppShell constructor, but this didn't work--which makes sense because the AppShell hasn't been fully constructed yet.
I found this answer, but it feels like it kind of skirts around the issue:
Maui AppShell - Navigate on Open
Where is the best place to inject some code that will run once on startup and can successfully navigate a .NET Maui app to a chosen page?
After playing around with overrides, it seems like overriding Application.OnStart works! Shell.Current is set at this point and navigation works.
Here's additional code that allows for asynchronous initialization and uses a Loading Page until the initialization is complete:
using MyApp.Services;
using MyApp.UI;
namespace MyApp;
public partial class App : Application
{
ConfigurationProviderService m_configProvider;
public App(ConfigurationProviderService configProvider)
{
m_configProvider = configProvider;
InitializeComponent();
MainPage = new LoadingPage();
}
protected override void OnStart()
{
var task = InitAsync();
task.ContinueWith((task) =>
{
MainThread.BeginInvokeOnMainThread(() =>
{
MainPage = new AppShell();
// Choose navigation depending on init
Shell.Current.GoToAsync(...);
});
});
base.OnStart();
}
private async Task InitAsync()
{
await m_configProvider.InitAsync();
}
}
I'd like to open a modal in Ionic 5 just opening a page. Without any action, just load the page and hop! you get your modal.
I've been reading the documentation at https://ionicframework.com/docs/api/modal#events but is too cryptic for me. Need some more elaboration...
I´ve fount severals examples out there of opening the modal with a click event, but that's not what I need.
Thanks in advance!
Look into Ionic's lifecycle hooks which let you execute code at different moments during a component's existence. You'll probably want to call a modal creating method inside of the ionViewDiDEnter hook within the component where you want the modal to appear.
Something like this:
export class YourPage {
constructor(public modalController: ModalController) { }
ionViewDidEnter() {
this.presentModal();
}
async presentModal() {
const modal = await this.modalController.create({
component: YourModalComponent
});
return await modal.present();
}
}
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.
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.
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.