I am using Ionic 4, I want to do different menu content in different page. I have add menuId inside my code, but I only get the second page menu. My first page menu is missing.
I think you should build 1 menu and then just populate its page list depending on the page being visited.
So your code would look something like this:
import { Component, OnInit } from '#angular/core';
import { Router, RouterEvent } from '#angular/router';
#Component({
selector: 'app-menu',
templateUrl: './menu.page.html',
styleUrls: ['./menu.page.scss'],
})
export class MenuPage implements OnInit {
selectedPath = '';
pages = getPages();
constructor(private router: Router) {
this.router.events.subscribe((event: RouterEvent) => {
if (event && event.url) {
this.selectedPath = event.url;
}
});
}
getPages() : any[] {
if (this.router.url === '/page1') {
return [
{
title: 'First Page with Tabs',
url: '/menu/first'
},
{
title: 'Second Page blank',
url: '/menu/second'
}
];
}
if (this.router.url === '/page2') {
return [
{
title: 'First Page with Tabs',
url: '/menu/first'
},
{
title: 'Second Page blank',
url: '/menu/second'
}
];
}
}
ngOnInit() {
}
}
And then display it like this:
<ion-split-pane>
<ion-menu contentId="content">
<ion-header>
<ion-toolbar color="primary">
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-menu-toggle auto-hide="false" *ngFor="let p of pages">
<ion-item [routerLink]="p.url" routerDirection="root" [class.active-item]="selectedPath.startsWith(p.url)">
<ion-label>
{{ p.title }}
</ion-label>
</ion-item>
</ion-menu-toggle>
<ion-item tappable routerLink="/login" routerDirection="root">
<ion-icon name="log-out" slot="start"></ion-icon>
Logout
</ion-item>
</ion-list>
</ion-content>
</ion-menu>
<ion-router-outlet id="content" main></ion-router-outlet>
</ion-split-pane>
Full tutorial about setting up a menu like this is available here:
How to Combine Ionic 4 Tabs and Side Menu Navigation [v4] - Ionic AcademyIonic Academy
Although the code I used as an example above for get getPages() is the bit you would write yourself.
Related
I am very new in karma jasmine test case. please help me out.
Typescript
import { Component, OnInit, ViewChild } from '#angular/core';
#Component({
selector: 'app-label',
templateUrl: './app-label.component.html',
})
export class LabelRenderer implements OnInit {
moreInfoItems;
#ViewChild('moreInfoModal') moreInfoModal;
constructor() { }
ngOnInit(): void { }
showModal(labelMenu) {
this.moreInfoItems = labelMenu?.content;
this.moreInfoModal.open();
}
}
HTML
<div
#moreInfoModal
[closeButton]="true"
>
<h2>More Information</h2>
<div class="modal-content">
<ul
data-size="large"
>
<li *ngFor="let item of moreInfoItems">
<div class="_text-bold _text-underline">{{item.heading}}</div>{{item.description}}
</li>
</ul>
</div>
</div>
I want to write unit test case for same but facing issue. Below code I tried for same.
it('should validate showModal method', () => {
component.moreInfoItems = {
content: [
{
"heading": "",
"description": ""
}
]
};
spyOn(component.moreInfoModal, 'open').and.returnValue({});
component.moreInfoModal.open();
expect(component.moreInfoModal.open).toHaveBeenCalledTimes(1);
spyOn(component, 'showModal').and.callThrough();
component.showModal(component.moreInfoItems);
expect(component.moreInfoItems).toHaveBeenCalled();
});
I saw some solution on stack overflow but most of the solutions I see with modal component. so request to help me out.
Thanks in advance.
I am new to ionic4. Before that i try ionic3 in that menu is working proper.
But now i migrate to ionic4.
I just create new project with inbuild menu option. It run successfully in web browser But When I run on my Android mobile device , Menu open but after clicking it did not close.
I use:
Ionic version:5.2.3
Node version:v10.16.3
Cordova version:9.0.0
First attempt:
my app.component.html file:
<ion-app>
<ion-menu type="overlay"side="start" contentId="menu-content">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-menu-toggle auto-hide="false" *ngFor="let p of appPages">
<ion-item [routerDirection]="'root'" [routerLink]="[p.url]" *ngFor="let p of appPages" (click)="togglemenu()">
<ion-icon slot="start" [name]="p.icon"></ion-icon>
<ion-label>
{{p.title}}
</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
</ion-content>
</ion-menu>
<ion-router-outlet main id="menu-content"></ion-router-outlet>
</ion-app>
my app.component.ts file:
import { Component } from '#angular/core';
import { Platform,MenuController } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss']
})
export class AppComponent {
public appPages = [
{
title: 'Home',
url: '/home',
icon: 'home'
},
{
title: 'List',
url: '/list',
icon: 'list'
}
];
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
public menu: MenuController,
private statusBar: StatusBar
) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
togglemenu(){
this.menu.close();
console.log("clikc");
}
}
Second attempt:
<ion-app>
<ion-split-pane contentId="menu-content" side="start">
<ion-menu type="overlay">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-menu-toggle auto-hide="false" *ngFor="let p of appPages">
<ion-item [routerDirection]="'root'" [routerLink]="[p.url]" *ngFor="let p of appPages">
<ion-icon slot="start" [name]="p.icon"></ion-icon>
<ion-label>
{{p.title}}
</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
</ion-content>
</ion-menu>
<ion-router-outlet main></ion-router-outlet>
</ion-split-pane>
</ion-app>
Looking at the ion-menu-toggle documentation it states:
"In case it's desired to keep ion-menu-toggle always visible, the autoHide property can be set to false."
https://ionicframework.com/docs/api/menu-toggle
It looks like you have this set to false. You can remove auto-hide="false" because it defaults to true.
I am having trouble adding an active class when clicking a link.
I have the dynamic class setup with a click listener that passes an argument to the function but the class does not update. I am not sure why. The 'Dashboard' link is red when page is refreshed so I know it is working to an extent.
<template>
<b-list-group>
<b-list-group-item
v-for="(link, index) in menu"
:key="index"
:href="link.sectionId"
:class="{active: link.title === selectedLink}"
:click="isActive(link.title)"
>
{{link.title}}
</b-list-group-item>
</b-list-group>
</template>
<script>
export default {
data() {
return {
selectedLink: 'Dashboard',
menu: [
{
title: 'Dashboard',
icon: labStuffs,
sectionId: '#'
},
{
title: 'Lactose intolerance',
icon: labStuffs,
sectionId: '#'
}
]
}
},
methods: {
isActive(title) {
this.selectedLink === title
}
}
}
</script>
<style scoped lang="scss">
.active {
background-color: red;
}
</style>
Expecting the background colour of clicked link to change. Only the dashboard link is red and whenever I click anything else, nothing happens.
Here is a working example of your code.
I changed the :click to #click and the following.
methods: {
isActive(title) {
this.selectedLink = title // Had === before
}
}
https://codesandbox.io/s/vue-template-y3k12?fontsize=14
I want to change a masthead text to the current route name that I am on. It only works on component mount, and does not fire on click. How do I get the changeHeaderTitle to run from the button click created by the router?
<template>
<div>
<nav class="navigation--navbar">
<router-link
class="navigation--links"
v-for="routes in links"
v-bind:key="routes.id"
#click='changeHeaderTitle'
:to="`${routes.page}`"
>{{routes.text}}</router-link>
</nav>
<div class="header--headline">
<h2 class="header--headline-text">{{headerTitle}}</h2>
</div>
</div>
</template>
<script>
export default {
name: 'Navigation',
data () {
return {
headerTitle: 'Boop',
links: [
{
id: 0,
text: 'Home',
page: '/Home'
},
{
id: 1,
text: 'Tutoring',
page: '/Tutoring'
}
]
}
},
methods: {
changeHeaderTitle: function () {
if (this.$route.path === '/') {
this.headerTitle = 'Home Header Here'
} else {
let routeName = this.$route.path.split('/')
this.headerTitle = routeName[1]
}
}
},
mounted: function () {
this.changeHeaderTitle()
}
}
</script>
Looks like you need to add .native modifier. Do:
<router-link
class="navigation--links"
v-for="routes in links"
v-bind:key="routes.id"
#click.native='changeHeaderTitle'
:to="`${routes.page}`"
>
{{routes.text}}
</router-link>
I'm following a tutorial here: https://www.youtube.com/watch?v=NJ9C7iY9350. Cannot understand why i'm doing click on a news and the news-detail is always the same, i'm checking my code and its the same as in the github. But don't know why cannot see the news-detail of every news, just remains the first news i do the click.
Attach my code:
NEWS
TS
goToNews(article) {
this.newsService.currentArticle = article;
console.log(article)
this.router.navigate(['/tabs/news-detail']);
}
getNews() {
this.newsService.getData(`top-headlines?countries=${this.selectedCountry}&category=technology`)
.subscribe(data => {
this.news = data;
console.log(this.selectedCountry)
})
}
HTML
<ion-list *ngIf="!isResult">
<ion-item *ngFor="let country of countries" (click)="selectCountry(country)">
{{ country }}
</ion-item>
</ion-list>
<ion-card *ngFor="let article of news?.articles" (click)="goToNews(article)">
<ion-card-content>
<ion-card-title>{{ article.title }}</ion-card-title>
</ion-card-content>
</ion-card>
NEWS-DETAILS
TS
export class NewsDetailPage implements OnInit {
article
constructor(private newsService: NewsService) { }
ngOnInit() {
this.article = this.newsService.currentArticle;
console.log(this.article)
}
}
tabs.router.module.ts
....
{ path: 'news', loadChildren:'../news/news.module#NewsPageModule' },
{ path: 'news-detail', loadChildren:'../news-detail/news-detail.module#NewsDetailPageModule' },
....
Finally i resolved it:
ionViewWillEnter() {
this.article = this.newsService.currentArticle;
console.log(this.newsService.currentArticle)
}
Doing this it always change everytime as i do click on a new "news"