Background
I am making a exercise warm-up app. I've conceptually segmented it into a workout tab and a settings tab. In a linear fashion the workout tab lets one pick a workout plan ChooseWorkout.vue then an exercise ChooseLifts.vue then the weight ChooseWeight.vue and it will display an appropriate warmup.
The aforementioned components are working correctly and link to each other in the correct linear fashion.
What I want to do
I want to add tabbed navigation so a user can switch between the settings and the workout portion components of the app. The tabs I am making have a settings button and a workout button.
Apps flow
The problem
When I integrate the ion-tabs the main tab buttons correctly display the desired 2 components (ChooseWorkout.vue and Settings.vue) when clicked. But my problem is the router no longer
works. So when I navigate from the ChooseWorkout.vue to the ChooseLifts.vue I get a blank screen, but the tabs at the bottom of the app are visible.
The url for this navigation is http://localhost:8080/#/lifts/StrongLifts%205x5 (it works prior to the ion-tabs integration were <ion-vue-router /> was solely used on main.js).
Code
App.vue
<template>
<div id="app">
<ion-app>
<ion-tabs>
<ion-tab tab="workout">
<ion-vue-router />
</ion-tab>
<ion-tab tab="settings">
<Settings />
</ion-tab>
<template slot="bottom">
<ion-tab-bar>
<ion-tab-button tab="workout">
<ion-icon name="body-outline" />
<ion-label>Workouts</ion-label>
</ion-tab-button>
<ion-tab-button tab="settings">
<ion-icon name="body-outline" />
<ion-label>Settings</ion-label>
</ion-tab-button>
</ion-tab-bar>
</template>
</ion-tabs>
</ion-app>
</div>
</template>
COPY TO CLIPBOARD SELECT ALL
ChooseWorkout.vue
<template>
<ion-page>
<ion-header>
<ion-toolbar color="primary">
<ion-title>Choose Workout</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<ion-list>
<div v-for="workout in workouts" v-bind:key="workout">
<ion-item>
<ion-label>
<h1>{{workout.name}}</h1>
<p>{{workout.by}}</p>
</ion-label>
<router-link :to="{path:`lifts/${workout.name} `}">
<ion-button>Select</ion-button>
</router-link>
</ion-item>
</div>
</ion-list>
</ion-content>
</ion-page>
</template>
<script>
import { add } from "ionicons/icons";
import { addIcons } from "ionicons";
addIcons({
"ios-add": add.ios,
"md-add": add.md
});
export default {
name: 'ChooseWorkout',
data() {
return {
workouts: [
{name: 'Starting Strength', by: 'Mark Rippetoe'},
{name: 'StrongLifts 5x5', by: 'Mehdi'},
{name: 'GreySkull LP', by: 'John Sheaffer'},
{name: 'Max Single', by: 'n/a'}
]
}
},
methods: {
}
};
</script>
<style scope></style>
main.js
const router = new IonicVueRouter({
routes: [
{
path: "/",
redirect: "/workout"
},
{
path: "/settings",
name: "settings",
component: Settings
},
{
path: "/workout",
component: ChooseWorkout
},
{
path: "/lifts/:workout",
component: ChooseLifts
},
{
path: "/lifts/:workout/:excercise",
component: ChooseWeight
},
]
});
Your can use nested route in vue to accomplish that
https://ionicframework.com/docs/vue/navigation#working-with-tabs
Related
In my app when i receive new notification I want to render it notifications component . Now problem is It is not necessary that I always have opened that component on my screen. maybe I am on another component but when I want to see notification whenever I open that component. I am receiving real time notification in my main.js file.
PushNotifications.addListener('pushNotificationReceived',
async (notification) => {
//Notification
}
);
This file is available globally
There is component Notification In this Component i have list of notification i want to render that notification in this list.
Is this possible?
Here is component notification
<template>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-title>Notifications</ion-title>
<ion-buttons slot="start">
<ion-menu-button menuId="custom" auto-hide="false"></ion-menu-button>
</ion-buttons>
<ion-buttons slot="primary">
<ion-button color="secondary" #click="handleSignOut">
<ion-icon slot="icon-only" :icon="logOut"></ion-icon>
</ion-button>
</ion-buttons>
<ion-buttons slot="primary"> </ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Notifications</ion-title>
</ion-toolbar>
</ion-header>
<ion-title>{{ msg }}</ion-title>
<ion-list v-if="this.notifications.length > 0">
<ion-item
v-for="(notification, index) in this.notifications"
:key="index"
>
<ion-label #click="() => router.push(`${notification.data.actionURL}`)">
{{ notification.data.actionText }}
</ion-label>
</ion-item>
</ion-list>
<ion-toolbar v-else>
<ion-title size="large" align="center">No Notification</ion-title>
</ion-toolbar>
</ion-content>
<side-menu />
</ion-page>
</template>
<script>
import {
IonPage,
IonHeader,
IonToolbar,
IonTitle,
IonContent,
IonIcon,
IonButtons,
IonButton,
IonList,
IonItem,
IonLabel,
} from "#ionic/vue";
import { logOut } from "ionicons/icons";
import { mapActions } from "vuex";
import { useRouter } from "vue-router";
import SideMenu from "./SideMenu.vue";
import { TokenService } from "#/services/token.service";
export default {
name: "Tab1",
components: {
IonHeader,
IonToolbar,
IonTitle,
IonContent,
IonPage,
IonIcon,
IonButtons,
IonButton,
IonList,
IonItem,
IonLabel,
},
data() {
return {
msg: "",
notifications: {},
};
},
},
mounted(){
this.notifications= TokenService.getUserInfo().unread_notifications
}
};
</script>
BACKGROUND:
For some time all the click events were working for my Ionic app, then out of no where they have stopped. I have two floating action buttons that once had working click events; one would trigger a JS alert popup, and the other would open a modal.
These click events no longer work, the only elements that have working click events now are my ion-tab-buttons.
WHAT I HAVE TRIED/TESTED:
I have tried unwrapping these elements out of ion-items and ion-lists, still no change.
A simple ion-button as a replacement, still no change.
Moving the ion-button outside of the card element just below the opening ion-content tag, still no change.
Moving the ion-button outside of the ion-content; just above the tabs, still no change.
Any help is greatly appreciated.
contact.page.html
<ion-header class="navbar">
<div class="icons">
<ion-buttons slot="start">
<ion-menu-button color="tertiary"></ion-menu-button>
</ion-buttons>
<img src="assets/logo.png" />
</div>
</ion-header>
<ion-content text-center>
<ion-card>
<ion-card-header>
<ion-card-title>Contact Us</ion-card-title>
<ion-card-subtitle>BOUTIQUE SOLICITORS</ion-card-subtitle>
</ion-card-header>
<br>
<ion-card-content>
<ion-label><b>Head Office: Wembley</b>
<br>
Boutique Immigration Solicitors, 10th Floor Tower, 1 Olympic Way, Wembley, Middlesex HA9 0NP
DX: 51165 Wembley Park
We are located just 5 minutes from Wembley Park Station. There is a car park behind our office.
</ion-label>
<br>
<br>
<ion-list text-left>
<ion-item>
<ion-label>Call us on 0800 3881 0211</ion-label>
<ion-fab-button color="secondary" slot="end" size="small" (click)="callAlert()">
<ion-icon name="call"></ion-icon>
</ion-fab-button>
</ion-item>
<ion-item>
<ion-label>Email at admin#boutiquesolicitors.co.uk</ion-label>
<ion-fab-button color="secondary" slot="end" size="small" (click)="modalEmail()">
<ion-icon name="mail"></ion-icon>
</ion-fab-button>
</ion-item>
</ion-list>
</ion-card-content>
</ion-card>
</ion-content>
<ion-tabs>
<ion-tab-bar slot="bottom">
<ion-tab-button (click)="about()">
<ion-icon name="information-circle-outline"></ion-icon>
<ion-label>About Us</ion-label>
</ion-tab-button>
<ion-tab-button (click)="dashboard()">
<ion-icon color="blue" name="home"></ion-icon>
<ion-label>Dashboard</ion-label>
</ion-tab-button>
<ion-tab-button class="activeTab">
<ion-icon name="contacts"></ion-icon>
<ion-label>Contact Us</ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
contact.page.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router'
import { CallNumber } from '#ionic-native/call-number/ngx';
import { ModalController, AlertController } from '#ionic/angular';
import { EmailPage } from '../email/email.page';
#Component({
selector: 'app-contact',
templateUrl: './contact.page.html',
styleUrls: ['./contact.page.scss'],
})
export class ContactPage implements OnInit {
constructor(private router: Router, private callNumber: CallNumber, private alertController: AlertController, private modalController: ModalController) { }
ngOnInit() {
}
about() {
console.log('clicked about')
this.router.navigate(['members/menu/about'])
}
dashboard() {
console.log('clicked dashboard')
this.router.navigate(['members/menu/dashboard'])
}
async callAlert() {
console.log('method executed')
const callAlert = await this.alertController.create({
message: "Are you sure you want to call Boutique Solicitors?",
buttons: [{
text: "Cancel",
role: "cancel"
},
{
text: "Call",
handler: () => {this.callBS()}
}
]
});
callAlert.present()
}
async callBS() {
this.callNumber.callNumber("07847948252", false)
.then(res => console.log('Launched dialer!', res))
.catch(err => console.log('Error launching dialer', err))
}
async modalEmail() {
const modal = await this.modalController.create ({
component: EmailPage
});
modal.present();
}
}
Well, I ended up figuring it out myself. The issue is that when ion-tabs are placed outside of the 'ion-content' at the bottom, if you inspect element on Chrome Dev Tools you can see that for some reason their "click-zone" takes up the whole page, and is indexed in front of all other elements. Trying to use "z-index" css property will not resolve the issue.
The fix is to wrap the ion-tabs inside an ion-toolbar, below the closing 'ion-content' tag. This will fix the click-zone to the restricted ion-toolbar height, which resolves the issue. All other page elements (click) events will now fire. This also fixes the issue of when tabs can prevent a page from scrolling.
Tested on both Android and iOS.
Ciao ciao.
The answer provided here is not correct. There is a misunderstanding on how tabs work from OP. Tabs are meant to be full page UI components, and are not meant to be embed in other pages/components. Meaning that they should be the only content in a page.
<ion-tabs>
<ion-tab-bar slot="bottom">
<ion-tab-button tab="tab1">
<ion-icon name="triangle"></ion-icon>
<ion-label>Tab 1</ion-label>
</ion-tab-button>
<ion-tab-button tab="tab2">
<ion-icon name="ellipse"></ion-icon>
<ion-label>Tab 2</ion-label>
</ion-tab-button>
<ion-tab-button tab="tab3">
<ion-icon name="square"></ion-icon>
<ion-label>Tab 3</ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
This way the tabs are responsible for render the nested content, and events work as expected.
The answer from #mhartington above, is the correct answer. For Angular, tabs should be the page that loads other pages as child modules inside tabs-routing.module.ts.
Well, I ended up figuring it out myself. The issue is that when ion-tabs are placed outside of the 'ion-content' at the bottom, if you inspect element on Chrome Dev Tools you can see that for some reason their "click-zone" takes up the whole page, and is indexed in front of all other elements. Trying to use "z-index" css property will not resolve the issue.
The fix is to wrap the ion-tabs inside an ion-toolbar, below the closing 'ion-content' tag. This will fix the click-zone to the restricted ion-toolbar height, which resolves the issue. All other page elements (click) events will now fire. This also fixes the issue of when tabs can prevent a page from scrolling.
Tested on both Android and iOS.
Ciao ciao.
that's exactly what i am searching thanks
I am using in my package.json:
#ionic/core: "^4.0.3",
#ionic/vue: "0.0.4",
vue: "^2.6.10",
vue-router: "^3.0.6"
furthermore:
I'm using the IonVueRouter from #ionic/vue
I've wrote an IonVuePage component, which has two other components, the HeaderSection (<ion-toolbar>), and the TabBar (<ion-tabs>). Between those components I've added a Tag, to add other components inside of this default layout.
However, If I am using a simple ion-button inside a new component (e.g. Home component), which is inside the <slot/> Tag of the IonVuePage component it is not clickable until:
I Wrap it inside of a <ion-buttons> Tag, or
I remove the TabBar component of the IonVuePage component.
What could explain that behaviour?
Do I have my mistake in combining of <ion-tabs> and IonVueRouter? Can I use both?
I've noticed, that the where the TabBar is placed in is overlying:
If I set the height of the diff to 10%, then the button is clickable, but unfortunately the TabBar is not visible anymore.
Here's my code:
IonVuePage component:
<template>
<ion-page
class="ion-page"
main>
<header-section
:title="title"
:show-back-button="showBackButton"/>
<slot name="content"/>
<tab-bar/>
</ion-page>
</template>
<script>
import TabBar from '#/components/page/TabBar';
import HeaderSection from '#/components/page/HeaderSection';
export default {
name: 'IonVuePage',
components: {
TabBar,
HeaderSection,
},
...
TabBar component:
<template>
<!-- Listen to before and after tab change events -->
<ion-tabs
#IonTabsWillChange="beforeTabChange"
#IonTabsDidChange="afterTabChange">
<ion-tab
tab="home"/>
<ion-tab
tab="request"/>
<template slot="bottom">
<ion-tab-bar >
<ion-tab-button tab="home">
<ion-icon name="home"/>
<ion-label>Schedule</ion-label>
<ion-badge>6</ion-badge>
</ion-tab-button>
<!-- Provide a custom route to navigate to -->
<ion-tab-button tab="request">
<ion-icon name="contacts"/>
<ion-label>Request</ion-label>
</ion-tab-button>
</ion-tab-bar>
</template>
</ion-tabs>
</template>
Home component:
<template>
<ion-vue-page
:title="welcometext"
:show-back-button="true">
<ion-content slot="content">
<ion-button #click="changeToRequest">change to request page!</ion-button>
<ion-buttons>
<ion-button
fill="solid"
#click="showModal">show modal! </ion-button>
</ion-buttons>
</ion-content>
</ion-vue-page>
</template>
},
...
App.vue:
<template>
<div id="app">
<ion-app>
<ion-vue-router />
</ion-app>
</div>
</template>
<script>
export default {
name: 'App',
};
</script>
router.js:
import Vue from 'vue';
import { IonicVueRouter } from '#ionic/vue';
import Home from '#/views/Home';
Vue.use(IonicVueRouter);
export default new IonicVueRouter({
mode: 'history', // for not having the # in the URL
routes: [
{
path: '/',
redirect: '/home',
},
{
path: '/home',
name: 'Home',
component: Home,
},
{
path: '/request',
name: 'Requet',
component: () => import('#/views/TestRequest'),
},
],
});
I appreciate any kind of help or advise.
Kind regards
I am using a v-navigation-drawer on my webpage, but i want to disable it on specific routes, for example on the landing page.
I am currently using the v-navigation-drawer in the App.vue file, as shown:
<v-app>
<v-navigation-drawer id ="nav"
persistent
:mini-variant="miniVariant"
:clipped="clipped"
v-model="drawer"
enable-resize-watcher
fixed
app
width="275"
mobile-break-point
>
<v-list style="width:275px">
<v-list-tile style="color: white"
value="true"
v-for="(item,i) in items"
:key="item.path"
#click="redirect(item.path)"
>
<v-list-tile-action style="color:#1872EF" >
<v-icon v-html="item.icon"></v-icon>
</v-list-tile-action>
<v-list-tile-content id="list">
<v-list-tile-title v-text="item.title"></v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
<v-toolbar
app
:clipped-left="clipped"
style="background-color:#FFFFFF"
>
<p style="color:#DFDEE3" > Menu </p>
<img src="./assets/agilebot.svg" height="44" width="150">
<v-toolbar-title id="title"></v-toolbar-title>
</v-toolbar>
Which is the best way to disable it in specific routes ?
You can do it by using v-if (or even v-show)
<v-navigation-drawer v-if="['home'].indexOf($route.name) === -1">
home being your landing page name in the router:
routes: [
{ path: '/', component: Home, name: "home" }, // names are arbitrary of course
And in array inside v-if just add list of route names where you don't want the drawer shown.
Simple to use with $route it returns current route name in $route.name
<v-navigation-drawer v-if="$route.name!='home'">
In Router
routes: [
{ path: '/', component: Home, name: "home" },
Question: How can I create a swipable side menu for an ionic v4 vuejs app?
So I'm new to ionic and have been trying to migrate an existing web app to ionic. Following the steps on the limited articles up on ionic4 with vue. I installed #ionic/core, added the CDN to the index file, and the ignore flag for [/ion/] web compoenets right before mounting Vue.
I'm currently getting this error: Menu: must have a "content" element to listen for drag events on.
I'm a bit unsure of what to follow as many of the articles out there are on ion v2 and v3, I know there were a few changed made to how the ui-components and based on ionic4 beta docs what I have seems to be correct:'
<script lang="ts" src="./Layout.ts"></script>
<template>
<div class="layoutComponent">
<ion-page>
<ion-menu>
<ion-header>
<ion-toolbar color="primary">
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-list-header>
Navigate
</ion-list-header>
<ion-item>
<router-link :to="{name: 'link 1'}">
<ion-label full>
<eg-localizer token="1"></localizer>
</ion-label>
</router-link>
</ion-item>
<ion-item>
<router-link :to="{ name: 'link2'}">
<ion-label full>
<localizer token="2"></localizer>
</ion-label>
</router-link>
</ion-item>
<ion-item>
<a target="_blank" href="https://foo.com">
<ion-label full>
<localizer token="external link 3"></localizer>
</ion-label>
</a>
</ion-item>
</ion-list>
</ion-content>
</ion-menu>
<!-- main point of entry for app content -->
<slot></slot>
</ion-page>
</div>
</template>
The documentation on ionic framework it's a bit unclear or incomplete, but I was able to make the menu working:
<template>
<ion-menu side="start" content-id="menu-content">
<ion-header>
<ion-toolbar color="primary">
<ion-title>Start Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content id="menu-content">
<ion-list lines="full">
<ion-item v-for="item in items" :key="item.name">
<ion-icon :name="item.icon" slot="start"></ion-icon>
<ion-label>{{ item.name }}</ion-label>
</ion-item>
</ion-list>
</ion-content>
</ion-menu>
</template>
<script>
export default {
data () {
return {
items: [
{ name: 'Home', icon: 'home', href: 'home' },
{ name: 'About', icon: 'information-circle', href: 'about' },
{ name: 'Articles', icon: 'list-box', href: 'articles' },
{ name: 'Log out', icon: 'logout', href: 'logout' }
]
}
}
}
</script>
The key is here:
<ion-menu side="start" content-id="menu-content">
and here
<ion-content id="menu-content">
Hope this helps anyone.
For Ionic 6 + Vue js 3.0 make sure you have your component <ion-router-outlet /> inside a <ion-content>, and that ion-content should have the id you have specified in content-id parameter for the menu.
<ion-content id="main">
<ion-router-outlet />
</ion-content>