Ionic router failed - ionic-framework

I have used ion-tabs and side-menu for change route the app, both uses routerLink. And when i press Home tab in ion-tab to go back to home page inside other pages, route changed to home but home page constructor method and onInit methods does not invoke.
side-menu.component.ts
<ion-app>
<ion-split-pane contentId="main-content">
<ion-menu *ngIf="isAuthenticated$ | async" contentId="main-content" type="overlay">
<ion-content>
<ion-list id="inbox-list">
<div class="menu-header">
<ion-list-header>
<img src="assets/wa-logo.ico">
</ion-list-header>
<ion-note></ion-note>
</div>
<ion-menu-toggle auto-hide="false" *ngFor="let p of appPages; let i = index">
<ion-item (click)="selectedIndex = i" routerDirection="root" [routerLink]="[p.url]" lines="none" detail="false" [class.selected]="selectedIndex == i">
<ion-icon slot="start" [ios]="p.icon + '-outline'" [md]="p.icon + '-sharp'"></ion-icon>
<ion-label>{{ p.title }}</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
</ion-content>
<ion-footer>
<ion-menu-toggle auto-hide="false">
<ion-item
(click)="logout()"
routerDirection="root"
lines="none"
detail="true"
>
<ion-icon
slot="start"
ios='log-out-outline'
md="log-out-sharp"
></ion-icon>
<ion-label> Logout </ion-label>
</ion-item>
</ion-menu-toggle>
</ion-footer>
</ion-menu>
<ion-router-outlet id="main-content"></ion-router-outlet>
<ion-tabs *ngIf="isAuthenticated$ | async">
<ion-tab-bar [translucent]="true" slot="fixed">
<ion-tab-button (click)="onClick()">
<ion-icon name="home"></ion-icon>
<ion-label> Home </ion-label>
</ion-tab-button>
<ion-tab-button [routerLink]="['/features/new-request']">
<ion-icon name="document-text"></ion-icon>
<ion-label> New Request </ion-label>
</ion-tab-button>
<ion-tab-button [routerLink]="['/features/prev-requests']">
<ion-icon name="reader"></ion-icon>
<ion-label> All Requests </ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
</ion-split-pane>
</ion-app>
So if i go inside prev-request page using ion-tab and once using hardware back button or ion-toolbar back button to changes route back to home page constructor and ngOnInit does not invoke, but if i route using side menu and go back with hardware back button or ion-toolbar back button constructor and ngOnInit methods are invoked.
prev-req.page
constructor(private _preReqService: PrevReqService,private platform: Platform,
private _modal: ModalService,
private _router: Router) {
this.platform.backButton.subscribeWithPriority(10, () => {
this._router.navigate(['/features/home'])
});
}
Still i don't have any clue why this happens.
Any idea why this happens ?

If you want to execute a function every time you go to a page Use Ionic Page Life Cycle.
ionViewWillEnter: Fired when the component routing to is about to animate into view.
ionViewDidEnter: Fired when the component routing to has finished animating.
ionViewWillLeave: Fired when the component routing from is about to animate.
ionViewDidLeave: Fired when the component routing to has finished animating.
export class ExamplePage implements OnInit {
constructor(){
}
ionViewWillEnter(){
console.log('Will Enter Fired') // will fire every time to go to a page.
}
}
Ionic Life Cycle Docs

Related

Ionic 6 ionViewWillEnter cannot read property 0 of undefined

I am learning ionic. So i have added data to an array declared in a service. When i go back to the lists page, ngOnInit will not execute if i have been to that page before. To load the data i need to use ionViewWillEnter or ionViewDidEnter. However, when i move the function call to the ionViewWillEnteri get the following error:
ERROR TypeError: Cannot read property '0' of undefined
at DiscoverPage_Template (template.html:39)
at executeTemplate (core.js:9544)
at refreshView (core.js:9413)
at refreshComponent (core.js:10579)
at refreshChildComponents (core.js:9210)
at refreshView (core.js:9463)
at refreshEmbeddedViews (core.js:10533)
at refreshView (core.js:9437)
at refreshComponent (core.js:10579)
at refreshChildComponents (core.js:9210)
The only way i can get rid of the above error is by calling the function in both ngOnInIt and ionViewWillEnter.
loadedPlaces: Place[];
listedLoadedPlaces: Place[]; //for virtual scroll
constructor(private placesService: PlacesService, private menuCntrl: MenuController) { }
ngOnInit() {
console.log('ngOnInIt');
this.loadData();
}
ionViewWillEnter(){
console.log('ionViewWillEnter');
this.loadData();
}
loadData(){
this.loadedPlaces = this.placesService.places; //getter property
//for the virtual scroll
this.listedLoadedPlaces = this.loadedPlaces.slice(1);
}
I have also tried declaring an empty array and then removing the function call from ngOnInit. In this case i get following issue:
core.js:6157 ERROR TypeError: Cannot read property 'title' of undefined
at DiscoverPage_Template (template.html:39)
at executeTemplate (core.js:9544)
at refreshView (core.js:9413)
at refreshComponent (core.js:10579)
at refreshChildComponents (core.js:9210)
at refreshView (core.js:9463)
at refreshEmbeddedViews (core.js:10533)
at refreshView (core.js:9437)
at refreshComponent (core.js:10579)
at refreshChildComponents (core.js:9210)
My environment
node: v14.15.5
npm: 6.14.11
angular: 11.2.0
ionic: 6.13.1
How can i solve this issue?
Update:HTML
<ion-header>
<ion-toolbar>
<!--menu drawer-->
<ion-buttons slot="start">
<ion-menu-button menu="menu1"></ion-menu-button>
</ion-buttons>
<ion-title>Discover Places</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-segment value="all" (ionChange)="segmentChanged($event)">
<ion-segment-button value="all">All Places</ion-segment-button>
<ion-segment-button value="bookable">Bookable Places</ion-segment-button>
</ion-segment>
<ion-grid>
<!--open the side drawer manually -->
<ion-row>
<ion-button fill="clear" (click)="onMenuDrawerOpen()">
Menu
<ion-icon slot="start" name="apps-outline"></ion-icon>
<ion-icon slot="end" name="checkmark-done-outline" color="primary"></ion-icon>
</ion-button>
</ion-row>
<!--Featured place-->
<ion-row>
<ion-col size="12" size-sm="8" offset-sm="2" class="ion-text-center">
<ion-card>
<ion-card-header>
<ion-card-title>{{ loadedPlaces[0].title }}</ion-card-title>
<ion-card-subtitle>{{ loadedPlaces[0].price | currency }} / Night</ion-card-subtitle>
</ion-card-header>
<ion-img [src]="loadedPlaces[0].imageUrl"></ion-img>
<ion-card-content>
<div>{{ loadedPlaces[0].description}}</div>
</ion-card-content>
<div class="ion-text-right">
<!--fill Clear mean no background -->
<ion-button fill="clear" color="primary" routerDirection="forward" [routerLink]="['/', 'places', 'tabs', 'discover', 'place', loadedPlaces[0].id, 'detail']">
More
<ion-icon slot="start" name="star"></ion-icon>
<ion-icon slot="end" name="arrow-forward-circle-outline" color="primary"></ion-icon>
</ion-button>
</div>
</ion-card>
</ion-col>
</ion-row>
<!--Other places-->
<ion-row>
<ion-col size="12" size-sm="8" offset-sm="2" class="ion-text-center">
<!--since using scroll, removed the for loop from the ion-item moved it to the ion-virtual-scroll-->
<!--it takes the items property -->
<!--get the approxItemHeight using the dev tools and picking the height of an ion-item. The default is 40px-->
<ion-virtual-scroll [items]="listedLoadedPlaces" approxItemHeight="60px">
<!--<ion-list>-->
<!--Excluding the featured item above-->
<!--<ion-item *ngFor="let place of loadedPlaces.slice(1); let i = index" [routerLink]="['/', 'places', 'tabs', 'discover', 'place', place.id, 'detail']" detail>-->
<ion-item [routerLink]="['/', 'places', 'tabs', 'discover', 'place', place.id, 'detail']"
detail
*virtualItem="let place">
<ion-thumbnail slot="start">
<ion-img [src]="place.imageUrl"></ion-img>
</ion-thumbnail>
<ion-label>
<h2>{{ place.title}}</h2>
<p>{{ place.description }}</p>
</ion-label>
</ion-item>
<!--</ion-list>-->
</ion-virtual-scroll>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
I had to check for the null. Changing to following fixed the issue, did it for all the properties:
loadedPlaces[0]?.title

Stencil: <ion-nav> inside <ion-pane-split> don't work properly

these are my stencil and ionic version
"dependencies": {
"#ionic/core": "one"
},
"devDependencies": {
"#stencil/core": "1.0.0-beta.8"
}
I'm trying to use the <ion-menu> inside a <ion-split-pane> like in a ionic app, this is my code (this is the original repo of this code https://github.com/modemlooper/stencil-pwa-sidemenu ):
app-root.tsx
[...]
render() {
return (
<ion-app>
<ion-router useHash={false}>
<ion-route url="/" component="app-home" />
<ion-route url="/profile/:name" component="app-profile" />
</ion-router>
<ion-split-pane when="lg">
<ion-menu side="start">
<ion-header>
<ion-toolbar color="primary" />
</ion-header>
<ion-content forceOverscroll={false}>
<ion-list>
<ion-menu-toggle autoHide={false}>
<ion-item href="/">
<ion-icon slot="start" name="home" />
<ion-label>Home</ion-label>
</ion-item>
</ion-menu-toggle>
<ion-menu-toggle autoHide={false}>
<ion-item href="/profile/piero">
<ion-icon slot="start" name="person" />
<ion-label>Profile</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav main />
</ion-split-pane>
</ion-app>
);
}
[...]
The problem is that <ion-nav main /> gives me this error:
And without "main" the split pane don't work properly
This is the expected behaviour
How is it possible to fix this? I don't get how to use properly the ion menu inside a split pane...
Thank you so much
I have the split-pane working in an app. There are a couple differences with your implementation:
ion-nav is wrapped in an ion-content element with an ID attribute
The ion-contents ID is referenced in ion-split-pane[contentId] and ion-menu[contentId]
<ion-split-pane contentId="main-content">
<ion-menu contentId="main-content">
...
</ion-menu>
<ion-content id="main-content">
<ion-nav />
</ion-content>
</ion-split-pane>

FAB Button does not have backdrop to close when theuser clicks outside the options

I would like to add css backdrop which allows the user to close FAB button options once it's clicked. I tried the following CSS solution from here but covers the options and cannot be seeing.
<button ion-button (click)="toggle!=toggle ">Add</button>
<div [ngClass]="{ 'blur' : toggle }">
your content
</div>
<!-- fab placed to the bottom & center -->
<ion-fab vertical="bottom" horizontal="center" slot="fixed">
<ion-fab-button (click)="toggle!=toggle ">
<ion-icon name="arrow-dropup"></ion-icon>
</ion-fab-button>
<ion-fab-list side="top">
<ion-fab-button><ion-icon name="logo-vimeo"></ion-icon></ion-fab-button>
<ion-fab-button><ion-icon name="logo-facebook"></ion-icon></ion-fab-button>
<ion-fab-button><ion-icon name="logo-twitter"></ion-icon></ion-fab-button>
<ion-fab-button><ion-icon name="restaurant"></ion-icon>
<div class="list-label">Meals</div>
</ion-fab-button>
</ion-fab-list>
</ion-fab>
<div [ngClass]="{ 'blur' : toggle }">
<ion-content
<ion-card class="welcome-card">
<ion-img src="/assets/shapes.svg"></ion-img>
<ion-card-header>
<ion-card-subtitle>Get Started</ion-card-subtitle>
<ion-card-title>Welcome to Ionic</ion-card-title>
</ion-card-header>
<ion-card-content>
<p>Now that your app has been created, you'll want to start building out features and components. Check out some of the resources below for next steps.</p>
</ion-card-content>
</ion-card>
</ion-content
</div>
CSS
.blur {
filter: blur(5px);
-webkit-filter: blur(5px);
transition: -webkit-filter 200ms linear;
}
We have a similar thing in our app, but we use the backdrop as a loading screen with animations inside. I used a separate component with a high z-index:50 and if I want to have something on a higher level, I just add a lager number to the z-index of that element. I have ran some tests and it should work with ion-fab.

Ionic custom back button on single page

I looked at: https://ionicframework.com/docs/api/config/Config/
This page used an example where the tabsPlacement on ion-tabs was changed for that one element.
I tried to recreate this with:
<ion-header>
<ion-navbar backButtonIcon="close">
<ion-title>settings-edit</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
</ion-content>
There doesn't seem to be any changes with the navBar back button
There is no custom back button option in ionic simply change it as the button
<ion-header>
<ion-navbar hideBackButton="true">
<button ion-button menuToggle hideBackButton="true">
<ion-icon name="md-close" (click)="close()" ></ion-icon>
</button>
<ion-title>settings-edit</ion-title>
</ion-navbar>
</ion-header>
Try This Code and add below TS code in your page
close()
{
this.navctrl.pop();
}
As in the documentation, you should define it it in your app.module.ts
Add this to your #NgModule:
imports: [
BrowserModule,
IonicModule.forRoot(MyApp, {
backButtonIcon: 'close',
iconMode: 'ios',
modalEnter: 'modal-slide-in',
modalLeave: 'modal-slide-out',
tabsPlacement: 'bottom',
pageTransition: 'ios-transition'
})
]

Ionic 2 Multiple Menus on Multiple pages not working

I am building a tabbed application in Ionic 2 which has five tabs one being the home page. The tabs work fine. I am trying to add a menu for each tab page other than the home page. I have duplicated and added the code below for each of the 4 pages in the home page just changing the menu id;s and the content id's. Everything works fine for the first page I access the subsequent pages I access just don't do anything. I thought this would be quite simple but already have spent days looking for a solution. The docs just refer to different menus on one page not different menus on several pages. Newbie so guess its simple. Help please.
<ion-header>
<ion-navbar color="dark">
<button ion-button menuToggle="menujoinus">
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>JOIN US</ion-title>
</ion-navbar>
</ion-header>
<ion-menu [content]="joinuscontent" id="menujoinus">
<ion-content>
<ion-list>
<button ion-button block icon-right color="secondary" menuClose="menujoinus">Close
<ion-icon name="close"></ion-icon>
</button>
<button ion-item icon-left (click)="openPageFieldguides()">
<ion-icon name="compass"></ion-icon>
Field Guides
</button>
<button ion-item icon-left (click)="openPageVolunteers()">
<ion-icon name="clipboard"></ion-icon>
Volunteers
</button>
<button ion-item icon-left (click)="openPageOwner()">
<ion-icon name="key"></ion-icon>
Owners
</button>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav #joinuscontent [root]="rootPage"></ion-nav>
It's a bit confusing but you need to add all the menus to the app component - not any of the sub pages - and then reference whichever you need from the sub page using the MenuController. In some cases you may need to disable/enable menus on the sub page but depends on the situation. Take a look at http://ionicframework.com/docs/api/components/app/MenuController/ and the "Multiple Menus on the Same Side" and "Multiple Menus on Different Sides" for more information.
An example:
<!-- Menu 1 -->
<ion-menu id="menu-one" [content]="nav">
<ion-header>
<ion-navbar>
<ion-title>Menu 1</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item (click)="doSomething()" menuClose>
Item 1
</ion-item>
<ion-item (click)="doSomething()" menuClose>
Item 2
</ion-item>
</ion-list>
</ion-content>
</ion-menu>
<!-- Menu 2 -->
<ion-menu id="menu-two" [content]="nav">
<ion-header>
<ion-navbar>
<ion-title>Menu 2</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item (click)="doSomething()" menuClose>
Item 1
</ion-item>
<ion-item (click)="doSomething()" menuClose>
Item 2
</ion-item>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav #nav [root]="rootPage"></ion-nav>
And on the sub page:
import { Component } from '#angular/core';
import { MenuController } from 'ionic-angular';
#Component({
selector: 'sub-page',
templateUrl: 'sub-page.html'
})
export class SubPage {
constructor(public menuCtrl: MenuController) {
// menuCtrl.enable(false, 'menu-one');
menuCtrl.enable(true, 'menu-two');
}
toggleMenu() {
this.menuCtrl.toggle();
}
}
The gotcha is the doSomething() method needs to be on the app component, not the sub page component.