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
Related
I just installed vue-router 4 into a vue 3 application. When setting up my home route I keep getting the application displaying twice and even the navigation twice but cannot figure out why. I tried bringing in the Navigation component into App.vue and Home.vue but still shows twice. Is there something off that I am overlooking here?
router/index.js
import { createWebHistory, createRouter } from "vue-router";
import Home from "../components/Home";
import About from "#/components/About";
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/about",
name: "About",
component: About,
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
Navigation.vue
<template>
<div id="nav">
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
</div>
<router-view/>
</template>
<script>
export default {
name: 'Navigation'
}
</script>
Home.vue
<template>
<Header/>
<Navigation/>
<div>
<About/>
</div>
</template>
App.vue
<template>
<Home/>
</template>
<script>
import Home from "#/components/Home";
export default {
components: {Home}
}
</script>
Home contains Navigation (which contains <router-view>, rendering the current route) and About. Since About is always rendered, you'd see two of them if the current route were /about.
<template>
<Header/>
<Navigation/> <!-- contains router-view -->
<div>
<About/> <!-- ❌ always rendered in addition to current route -->
</div>
</template>
Your current route configuration has no child routes, so there should only be one <router-view>, and it's usually in the root component (App.vue):
App.vue:
<template>
<Header />
<Navigation />
<router-view />
</template>
Navigation.vue:
<template>
<div id="nav">
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
</div>
<!--<router-view/> ❌ move to App.vue -->
</template>
Home.vue:
<template>
<!--<Header/> ❌ move to App.vue -->
<!--<Navigation/> ❌ move to App.vue -->
<div>
<About />
</div>
</template>
demo
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>
I am using Vue after a long pause so sorry in advance for rather silly question.
I have a navigation component which is nested in layout component. The problem is that it is not visible on the page and in DevTools but I can see it in my Vue Chrome extension.
I feel like I am missing something really small but can't figure this out. Please help.
This my App.vue
<template>
<div id="app">
<router-view />
</div>
</template>
This is my Home page:
<template>
<Layout>
<h1>Home page</h1>
</Layout>
</template>
<script>
import Layout from '../layouts/Layout.vue';
export default {
name: 'home',
components: { Layout },
};
</script>
This is Layout component:
<template>
<div class="main">
<Navigation />
<slot />
</div>
</template>
<script>
import Navigation from '../components/Navigation.vue';
export default {
name: 'Layout',
components: { Navigation },
};
</script>
Everything is visible from Layout component except Navigation component. Here it is:
<template>
<div class="navigation">
<router-link :to="{ name: 'home' }">
Home
</router-link>
<nav>
<!-- Nav routes -->
</nav>
</div>
</template>
<script>
export default {
name: 'Navigation',
};
</script>
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
Is it possible to hide the vue-router from my login page? If so, how would I do that? On every page I have I see the menu, but on the Login page I don't want to see it.
Here is my code:
Login
<template>
<div>
<h1>Login</h1>
<form action="">
<label>naam</label>
<input type="text">
</form>
</div>
</template>
<script>
</script>
<style scoped>
h1 {
background-color: chartreuse;
}
</style>
App.vue
<template>
<div id="app">
<div class="routing">
</div>
<router-link to="/">Login</router-link>
<router-link to="/home">Home</router-link>
<router-view v-if="$route = 'login'"></router-view>
</div>
</template>
<script>
export default {
data () {
return {
}
}
}
</script>
Main.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
import Login from './Login.vue'
import Home from './Home.vue'
Vue.use(VueRouter);
const routes = [
{ path: '/', component: Login},
{ path: '/home', component: Home},
];
const router = new VueRouter({
routes,
mode: 'history'
});
new Vue({
el: '#app',
router,
render: h => h(App)
});
Home.vue
<template>
<div>
<h1>Home</h1>
<hr>
<router-view></router-view>
</div>
</template>
<script>
</script>
<style scoped>
h1 {
background-color: aquamarine;
}
</style>
I just had the same problem and found 2 approaches:
1. Using nested routes - http://router.vuejs.org/en/essentials/nested-routes.html
Basically you have to use your App.vue as kind of a placeholder, with all the elements that are shared between all the pages (in your case I believe that is none), and place <router-view></router-view> inside it. For you I believe that will be as simples as:
//App.vue
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
And you also will have to have another template that will hold your menu:
//Restricted.vue
<template>
<div id="restricted">
<div class="routing">
</div>
<router-link to="/">Login</router-link>
<router-link to="/home">Home</router-link>
<router-view></router-view>
</div>
</template>
And in your router should have something like:
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
import Login from './Login.vue'
import Home from './Home.vue'
import Restricted from '/.Restricted.vue';
Vue.use(VueRouter);
const routes = [
{ path: '/', component: Login},
{
path: '/restricted',
component: Restricted,
children: [
{ path: 'home', component: Home},
],
},
];
const router = new VueRouter({
routes,
mode: 'history'
});
new Vue({
el: '#app',
router,
render: h => h(App)
});
This way your Login page will be rendered at / and other pages (with menu) at /restricted/{other_page}. Using this approach the menu will not be displayed nor rendered.
2. Using v-if on the components that you do not want to render.
In you App.vue use v-if="this.$route.path !== '/'" on the elements that you do not want to be rendered, in your case, the router-link's. You could encapsulate them and apply v-if="this.$route.path !== '/'" to the encapsulation element (div?)
//App.vue
<template>
<div id="app">
<div class="routing" v-if="this.$route.path !== '/'">
<router-link to="/">Login</router-link>
<router-link to="/home">Home</router-link>
</div>
<router-view></router-view>
</div>
</template>
Regards.
You can use v-if for this:
<router-link v-if="!isOnLoginPage()" to="/">Login</router-link>
where isOnLoginPage can be a simple method, which returns true or false depending on current route.
isOnLoginPage: function() {
return this.$route.path === '/'
}
if your login path is '/login'
in your App.vue
<template>
<div id="app">
<div class="routing">
</div>
<router-link to="/" v-if="$route.fullPath !== '/login'">Login</router-link>
<router-link to="/home" v-if="$route.fullPath !== '/login'">Home</router-link>
<router-view v-if="$route.fullPath === '/login'"></router-view>
</div>
</template>
<script>
export default {
data () {
return {
}
}
}
</script>