Ionic 4 Tabs not rendering completely - ionic-framework

I'm having this weird problem, I have started a new app with Tabs and angular routing.
I have added a new Login page, and after login, the user is redirected to the tabs page.
The problem is that after the redirect, sometimes only one tab is rendered, and sometimes two tabs are rendered.
If I refresh the page or go directly to it, all 3 tabs are shown.
If I start the app on the Tabs page, again, all 3 tabs are shown.
AppRoutingModule:
const routes: Routes = [
{path: 'login', loadChildren: './login/login.module#LoginPageModule'},
{path: 'home', loadChildren: './tabs/tabs.module#TabsPageModule'},
{path: '', redirectTo: '/login', pathMatch: 'full'}];
TabsPageRoutingModule:
const routes: Routes = [
{
path: '',
component: TabsPage,
children: [
{
path: 'home',
outlet: 'home',
component: HomePage
},
{
path: 'about',
outlet: 'about',
component: AboutPage
},
{
path: 'contact',
outlet: 'contact',
component: ContactPage
}
]
},
{
path: '',
redirectTo: '/tabs/(home:home)',
pathMatch: 'full'
}];
LoginPage:
export class LoginPage implements OnInit {
responseData: any;
userData = {'email': '', 'password': ''};
constructor(public navCtrl: NavController, public apiService: ApiService, public toastCtrl: ToastController) {
}
login() {
this.apiService.login(this.userData).then((result) => {
this.responseData = result;
if (this.responseData.token) {
console.log(this.responseData);
localStorage.setItem('token', this.responseData.token);
this.navCtrl.goRoot('/home');
} else {
console.log('User already exists');
}
}, (err) => {
// Error log
console.log(err);
});
}
ngOnInit() {
}}
Any Ideas? Thanks!

As of today, November 1, 2018 the tabs in Ionic 4 (4.0.0-beta.15) have been completely changed.
https://github.com/ionic-team/ionic/blob/master/CHANGELOG.md#400-beta15-2018-11-01
Basically, they've updated the tabs to be a tab-bar of buttons that can be used to load ion-router-outlet, ion-content or ion-nav components.
Some other benefits of this refactor include:
Can now be written as a standalone Tab Bar (with no attached Tab)
Works with a navigation component or a plain content element
Works with shadow DOM and allows easy customization of the Tab Bar
Gives full control over the elements inside of the Tab Bar
Integrates nicely with other frameworks that have different ways of rendering element nodes

Try changing
this.navCtrl.goRoot('/home');
to
this.navCtrl.goRoot('/tabs'); to

step 1:
const routes: Routes = [
{
path: 'tabs',
component: TabsPage,
children: [
{
path: 'home',
outlet: 'home',
component: HomePage
},
{
path: 'about',
outlet: 'about',
component: AboutPage
},
{
path: 'contact',
outlet: 'contact',
component: ContactPage
}
]
},
{
path: '',
redirectTo: '/home/tabs/(home:home)',
pathMatch: 'full'
}];
step 2:
this.navCtrl.goRoot('/home');

I had the same problem.
After reviewing my HTML I realized that I had a problem, in the "ion-tab" the input "label" its empty and this caused the problem, the error:
<ion-tab label="" icon="medkit" href="/(entidades:entidades)">
<ion-router-outlet name="entidades">
</ion-router-outlet>
</ion-tab>
the solution for me:
<ion-tab label="The label of tab" icon="medkit" href="/(entidades:entidades)">
<ion-router-outlet name="entidades">
</ion-router-outlet>
</ion-tab>
I hope it helps you

Related

Setting opening page in app-routing module doesn't redirect as expected

I have walkthrough page built using ion-slides.
I had set this page to be the first page to open when the app had launched in app-routing.module.ts:
{
path: '',
redirectTo: 'walkthrough',
pathMatch: 'full'
},
However if I change the starting page to any other page the app will consistently start with the waklthourgh page:
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
All paths are set correctly:
{
path: 'walkthrough',
loadChildren: () => import('./walkthrough/walkthrough.module').then(m => m.WalkthroughPageModule)
},
{
path: 'login',
loadChildren: () => import('./auth/login/login.module').then( m => m.LoginPageModule)
},
Any input appreciated.
EDIT: adding login routing.module.ts:
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { LoginPage } from './login.page';
const routes: Routes = [
{
path: '',
component: LoginPage
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class LoginPageRoutingModule {}

How to do a lazy loaded ionic framework app with a login page

I have an app that is working great, but I want to move it behind a login page. The various modules are lazy-loaded and have been working great. However, when I change the app to always go to the login page first (where I will check login status and redirect to the app if logged in), I get an error about routes.
app-routing.module.ts
import { NgModule } from '#angular/core';
import { PreloadAllModules, RouterModule, Routes } from '#angular/router';
const routes: Routes = [
{ path: '', loadChildren: './login/login.module#LoginPageModule' }
// this next line was how the app routed before I tried adding the login page
// { path: '', loadChildren: './tabs/tabs.module#TabsPageModule' }
];
#NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
],
exports: [RouterModule]
})
export class AppRoutingModule {}
login.router.module.ts
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { LoginPage } from './login.page';
const routes: Routes = [
{ path: '', component: LoginPage },
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class LoginRoutingModule { }
login.page.ts
import { ChangeDetectionStrategy, Component } from '#angular/core';
import { Router } from '#angular/router';
import { Store } from '#ngrx/store';
import { AppState } from '../_store/store/app.store';
import { filter } from 'rxjs/operators';
#Component({
selector: 'app-login',
templateUrl: 'login.page.html',
styleUrls: ['login.page.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LoginPage {
constructor(private router: Router, private store: Store<AppState>) {
this.userSubscription = this.store.select(state => state.users.user).pipe(
filter(user => !!user)
).subscribe(user => {
if (user) {
// THIS IS WHERE THE ERROR HAPPENS
this.router.navigate(['/tabs']);
}
});
}
}
this.router.navigate(['/tabs']); is where the error happens:
ERROR Error: Uncaught (in promise): Error: Cannot match any routes.
URL Segment: 'tabs/behaviors' Error: Cannot match any routes. URL
Segment: 'tabs/behaviors'
I'm sure I'm missing something really obvious here. First attempt at lazy loading all the modules. I'm pretty certain I need to reference the tabs module in the login.page file somehow, or in the login.router.module. Any help would be greatly appreciated. The state check for user status works great, I've verified that all of that is working, it is just where it attempts to navigate if user is found.
Try to change to
const routes: Routes = [
{ path: '', redirectTo: 'login', pathMatch: 'full' },
{ path: 'login', loadChildren: './login/login.module#LoginPageModule' }
{ path: 'tabs', loadChildren: './tabs/tabs.module#TabsPageModule' }
];
With this code this.router.navigate(['/tabs']); you are routing to tabs, but you don't have it declare it. This is for the app.routing.ts file. Don't understand why you have the login.router.ts file.
So after following a suggestion above, and that giving me the same error, and finding no help in the docs for either angular or ionic, I went on a multi-hour change every combination of routings I could and finally something worked.
These are the routes in the app-routing.module.ts
{ path: 'login', loadChildren: './login/login.module#LoginPageModule' },
{ path: 'tabs', loadChildren: './tabs/tabs.module#TabsPageModule' },
{ path: '', redirectTo: 'login', pathMatch: 'full' },
This is the tabs.router.module.ts before the change that made it work:
{ path: 'tabs', component: TabsPage, children: [ .... ] },
{ path: '', redirectTo: 'tabs/behaviors', pathMatch: 'full' }
This is it now:
{ path: '', component: TabsPage, children: [ ... ] },
That's it. Finally figured it out when accidentally typing in the browser .com:8100/tabs/tabs/behaviors worked. Removing the path: 'tabs' in the tabs routing module fixed it. /tabs goes to the tabs routing, and then /behaviors is the child. My code had added a 2nd layer of /tabs in between the 1st and the /behavior.

How to trigger ionViewWillLeave in Ionic 4 with route in tabs.router.module

Lifecycle hooks ionViewWillLeave / ionViewDidLeave are not triggered when placing all pages routes in TabsPageRoutingModule.
We changed the routes from app-routing.module.ts to tabs.router.module.ts to get full view of the tabbar in the Ionic 4 app. The routes works perfectly.
When the routes were in app-routing.module.ts, the ionViewWillLeave was always triggered when leaving the page (and closing the present Observables). Now the ionViewWillLeave is not triggered when leaving the page.
Route in tabs.router.module.ts
const routes: Routes = [
{
path: 'tabs',
component: TabsPage,
children: [
{
path: '',
redirectTo: '/tabs/(home:home)',
pathMatch: 'full',
},
{
path: 'home',
outlet: 'home',
component: HomePage
},
{
path: 'chats',
outlet: 'chats',
component: ChatsPage
},
...
Logging failed for ionViewWillLeave in TS file
ionViewWillEnter() {
console.log('ionViewWillEnter'); // <- In console when entering
}
ionViewWillLeave() {
console.log('ionViewWillLeave'); // <- Not in console when leaving
}
Can't figure out why the ionViewWillLeave is not printed anymore. Any help is appreciated.
Route in app-routing.module.ts
const routes: Routes = [
{ path: '', loadChildren: './tabs/tabs.module#TabsPageModule' },
{ path: 'chats', loadChildren: './chats.module#ChatsPageModule' },
...
Logging success for ionViewWillLeave in TS file
ionViewWillEnter() {
console.log('ionViewWillEnter'); // <- In console when entering
}
ionViewWillLeave() {
console.log('ionViewWillLeave'); // <- In console when leaving
}
Solution for our problem
Breaking changes to tabs
4.0.0-beta.18 (2018-12-13)
Stopped using outlet/component in tab-router, now we directly place children pages in the tabbed path.
{
path: 'tabs',
component: TabsPage,
children: [
{
path: 'home',
children: [
{
path: '',
loadChildren: '../home/home.module#HomePageModule'
},
{
path: 'chats'
children: [
{
path: '',
loadChildren: '../chats/chats.module#ChatsPageModule'
}
]
},
...

Named router and nested routes in angular 6

Can someone please assist in navigating to a specific route. I've been sitting with this for hours now. Here's what I have:
const routes: Routes = [
{
path: '', redirectTo: 'home', pathMatch: 'full'
},
{
path: 'home',
component: MainlayoutComponent,
canActivate: [AuthenticatedGuard],
children: [
{ path: 'listmanagement', component: ListmanagementComponent, outlet: 'main' },
{
path: 'buildings', component: BuildingslistComponent, outlet: 'main',
children: [
{ path: '', redirectTo: 'buildings', pathMatch: 'full' },
{ path: 'building', component: BuildingdetailComponent },
{ path: 'building/:code', component: BuildingdetailComponent }
]
},
{
path: 'calendarandrates', component: CalendarandratesComponent, outlet: 'main',
children: [
{ path: '', redirectTo: 'calendarandrates', pathMatch: 'full' },
{ path: 'rescalendar', component: RescalendarlistComponent },
{ path: 'roomrates', component: ResratesmainComponent },
]
},
{ path: 'users', component: UsersComponent, outlet: 'main' },
]
},
{
path: 'login',
component: LoginlayoutComponent,
children: [
{ path: '', component: LoginComponent, outlet: 'login' },
]
},
{
path: '**',
component: NotfoundComponent,
canActivate: [AuthenticatedGuard],
outlet: 'main'
}
];
Then in my app.component I only have the primary router outlet:
<router-outlet></router-outlet>
This router outlet is suppose to load only one of the two layout components, maned loginlayout.component and mainlayout.component: One for when a user is not logged in (so as not to show the side nav and other toolbar items, this layout component only has a simple logo on the top left and header in the middle), and other layout component has side nav and more items on the toolbar. All this is working fine and I'm able to log in using the first layout and load the 2nd layout. The outlet routers in the respective layout pages are:
<router-outlet name="login"></router-outlet>
<router-outlet name="main"></router-outlet>
Somehow, once in the main layout component, I can navigate to the 1st level child (buildings, for example) using something like:
this.router.navigate(['/home', { outlets: { main: ['buildings'] } }])
I cannot seem to figure out how I can navigate to the 2nd later child (for example, once in the buildings component, I want to navigate to the (single) building item by clicking an edit (with param) or add (without param) new button
I've search and I only get examples with only one level child, but not 2 levels as I have in this example. Any help would be appreciated.
I fixed my issue and just carried on with the development. Now that I'm done, I thought I should just post my fix. I changed the routes to look like this:
const routes: Routes = [
/*==================================Main Outlet==================================*/
{
path: '', redirectTo: 'home', pathMatch: 'full'
},
{
path: 'home', component: MainlayoutComponent, canActivate: [AuthGuard],
children: [
{ path: '', component: HomeComponent, outlet: 'main' },
{ path: 'listmanagement', component: ListmanagementComponent, outlet: 'main' },
{ path: 'buildings', component: BuildingslistComponent, outlet: 'main' },
{ path: 'buildings/building/:code', component: BuildingdetailComponent, outlet: 'main' },
{ path: 'buildings/building', component: BuildingdetailComponent, outlet: 'main' },
{ path: 'buildings/allbedspaces', component: BedspacelistComponent, outlet: 'main' },
{ path: 'calendarandrates', component: CalendarandratesComponent, outlet: 'main' },
{ path: 'calendarandrates/rescalendar', component: RescalendarlistComponent, outlet: 'main' },
{ path: 'calendarandrates/roomrates', component: ResratesmainComponent, outlet: 'main' },
{ path: 'users', component: UsersComponent, outlet: 'main' },
{ path: 'users/myaccount', component: MyaccountComponent, outlet: 'main' },
{ path: '**', component: NotfoundComponent, canActivate: [AuthGuard], outlet: 'main' }
]
},
/*==================================Login Outlet==================================*/
{
path: 'login', component: LoginlayoutComponent,
children: [{ path: '', component: LoginComponent, outlet: 'login' } ]
}
];
Then when navigating to a route I just use the following code:
this.router.navigate(['/home', { outlets: { main: ['buildings', 'allbedspaces'] } }], { skipLocationChange: true })
skipLocationChange: true because I skip all my location changes when routing and always keep the base url since I do not want users to navigate through the app using the address bar

Ionic 4 how to navigate from tab page to non-tab page keeping tab?

In Ionic 4, I have an application with a tabs ( 5 pages Home, Search, Map, Info, Tarif)
From Search page i navigate to Detail page but i want to keeping the tab menu on Detail page.
I don't know if is possible ?
How do you configure the route ?
This is my:
app-routing.module.ts
`const routes: Routes = [
{ path: '', loadChildren: './tabs/tabs.module#TabsPageModule' },
{ path: 'map', loadChildren: './map/map.module#MapPageModule' },
{ path: 'search', loadChildren: './search/search.module#SearchPageModule' },
{ path: 'station', loadChildren: './station/station.module#StationPageModule' },
{ path: 'info', loadChildren: './info/info.module#InfoPageModule' },
{ path: 'tarif', loadChildren: './tarif/tarif.module#TarifPageModule' }
];`
and my `tabs.router.module.ts`
`const routes: Routes = [
{
path: 'tabs',
component: TabsPage,
children: [
{
path: 'home',
outlet: 'home',
component: HomePage
},
{
path: 'search',
outlet: 'search',
component: SearchPage
},
{
path: 'map',
outlet: 'map',
component: MapPage
},
{
path: 'info',
outlet: 'info',
component: InfoPage
},
{
path: 'tarif',
outlet: 'tarif',
component: TarifPage
}
]
},
{
path: '',
redirectTo: '/tabs/(home:home)',
pathMatch: 'full'
}
];`
The station page must be a child page of Search page ?
You do that using this setting in app.module.ts file.
IonicModule.forRoot(MyApp, {
tabsHideOnSubPages: false
})
As ionic tabs template have this provisioning to push any detail page with in the same tab navigation stack.
So you can do it like below to push your Detail view in same Search tab section.
this.navCtrl.push(DetailPage, { detailId: detailData.id });
by doing this you can push your detail page into same Tab page.
Hope this will helps!
You have to make the Detail page a child of the "tabs" routes. This works without displaying an icon for that page in the tab icon bar.
Add an entry into the "children" array in tabs.router.module.ts:
{
path: 'detail',
children: [
{
path: '',
loadChildren: '../detail/detail.module#DetailPageModule'
}
]
},
Then you may navigate to /tabs/detail, for example in a ion-button or similar by [routerLink]="['/tabs/detail']".
If you like, you may also define a redirect route in your app-routing.module.ts:
{ path: 'detail', redirectTo: '/tabs/detail' }
A drawback of this solution is, that the tab bar icon of your "Search" page will not be coloured when the "Detail" page is displayed. But this may be solved by additional CSS formatting.