When I open a new pop-up window using window.open, components such as v-app-bar and v-navigation-drawer show the same in the pop-up window.
I think it's because I added url to the router registered in the app so only router-view is replaced and the app screen is displayed in the pop-up window. How do I get a pop-up window to look completely new? Do I have two routes for pop-up windows? But how?
windowRef.value = window.open(uri, "", attr);
<App.vue>
<template>
<v-app>
<v-app-bar>
</v-app-bar>
<v-navigation-drawer>
</v-navigation-drawer>
<v-main>
<router-view/>
</v-main>
<v-app>
</template>
<router/index.ts> <main.ts>
const routes: Array<RouteRecordRaw> = [
{
path : '/child/ChildWinPop',
name : 'ChildWinPop',
component : ()=>import( '../components/ChildWinPop.vue' )
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
const app = createApp(App)
app.use(router)
Related
I am using vuex store state to show/hide Vuetify v-dialog in my NuxtJS app. Following are the code excerpt:
Vuex Store:
export const state = () => ({
dialogOpen: false
});
export const mutations = {
setDialogToOpen(state) {
state.dialogOpen = true;
},
setDialogToClosed(state) {
state.dialogOpen = false;
}
};
export const getters = {
isDialogOpen: state => {
return state.dialogOpen;
}
};
Dialog Component:
<v-dialog
v-model="isDialogOpen"
#input="setDialogToClosed"
max-width="600px"
class="pa-0 ma-0"
>
...
</v-dialog>
computed: {
...mapGetters("store", ["isDialogOpen"])
},
methods: {
...mapMutations({
setDialogToClosed: "store/setDialogToClosed"
})
}
This all works fine but when I redirect from one page to another page like below it stops working.
this.$router.push("/videos/" + id);
I hit browser refresh and it starts working again. Using the Chrome Vue dev tools, I can see the state is set correctly in the store as well as in the v-dialog value property as shown below
In Vuex store
In v-dialog component property
Yet the dialog is not visible. Any clue what is happening?
I am using NuxtJS 2.10.2 and #nuxtJS/Vuetify plugin 1.9.0
Issue was due to v-dialog not being wrapped inside v-app
My code was structured like this
default layout
<template>
<div>
<v-dialog
v-model="isDialogOpen"
#input="setDialogToClosed"
max-width="600px"
class="pa-0 ma-0"
>
<nuxt />
</div>
</template>
Below is the code for index page which replaces nuxt tag above at runtime.
<template>
<v-app>
<v-content>
...
</v-content>
</v-app>
</template>
So, in the final code v-dialog was not wrapped inside v-app. Moving v-app tag to default layout fixed it
<template>
<v-app>
<v-dialog
v-model="isDialogOpen"
#input="setDialogToClosed"
max-width="600px"
class="pa-0 ma-0"
>
<nuxt />
</v-app>
</template>
I have two sign up components that contain forms, one for those signing up as individuals and one signing up as businesses, I have a main page component with two large buttons labeled, "Click here to sign up as an individual", "Click here to sign up as a business'. How do I link these components on Vue? I am hoping that upon click of the button the component renders on the same page and not a new tab.
Thanks in advance!
So far,
Attempted to configure the router.js(I have a feeling this might be where my issue is)
Added the routes to the v-button
App.vue
<template>
<v-app>
<v-btn dark to="./components/CompanySignUp"> Sign up as a Company </v-btn>
<v-btn dark to="./components/FreelanceSignUp"> Sign up as a Freelancer
</v-btn>
</v-app>
</template>
<script>
export default {
name: "App",
components: {},
data: () => ({
//
})
};
</script>
router.js
import Vue from "vue";
import Router from "vue-router";
import CommpanySignUp from "./components/CompanySignUp";
import FreelancerSignUp from "./components/FreelancerSignUp";
Vue.use(Router);
const router = new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "./components/CompanySignUp",
name: "Company Sign Up",
component: CommpanySignUp
},
{
path: "./components/FreelancerSignUp",
name: "Freelancer Sign Up",
component: FreelancerSignUp
}
]
});
main.js
import Vue from "vue";
import App from "./App.vue";
import vuetify from "./plugins/vuetify";
import 'material-design-icons-iconfont/dist/material-design-icons.css'
import VueRouter from "vue-router";
Vue.use(VueRouter);
Vue.config.productionTip = false;
new Vue({
vuetify,
render: h => h(App)
}).$mount("#app");
This sounds like a good opportunity to use vue-router, but there are multiple approaches to this problem. Depending on scope, there may be more than one good answer. There is a comment above about using emitters and props, which is fine, but I would recommend using vue-router because it's made for this kind of dynamic component switching. If you've used the vue-cli it should be trivial to add, but the following example uses the standalone CDNs for brevity. This can all be done in separate files and the vue-cli will already have a nice scaffold for you if you want to see how that's done.
const Main = {
template: `
<div>
<router-link to="/register/business">Register for business</router-link>
<router-link to="/register/personal">Register for personal</router-link>
</div>
`
};
const RegistrationPage = { template: '<router-view></router-view>' };
const BusinessRegistration = {
template: `
<h1>Business</h1>
`
};
const PersonalRegistration = {
template: `
<h1>Personal</h1>
`
};
const routes = [
{
path: '/',
component: Main
},
{
path: '/register',
component: RegistrationPage,
children: [
{
path: 'business',
component: BusinessRegistration
},
{
path: 'personal',
component: PersonalRegistration
}
]
}
];
const router = new VueRouter({
routes
});
const app = new Vue({
router
}).$mount('#app');
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://unpkg.com/vue-router#2.0.0/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-view></router-view>
</div>
</body>
</html>
There are multiple benefits to this approach:
Vue router is supported pretty well by the Vue community so you can find lots of documentation and examples.
Your end user can visit mysite.com/register/business and land on the correct page, rather than having to go through clicking on the button if they decide to leave your page and come back.
Much of the logic is abstracted away by the library rather than having to do complex conditional logic and event emitters.
This is a very simple example that relies heavily on the "getting started" docs here. If you did start your project with the vue-cli, you should be able to run vue add vue-router, which should do some setup for you if you missed that step in the project creation process, otherwise you can use npm and set things up manually.
Assuming that your vue router is already working and you already displayed your component What you did is already correct, just follow these steps to make it working.
First put a router view in your main app . like below
<v-app>
<v-btn dark to="./components/CompanySignUp"> Sign up as a Company </v-btn>
<v-btn dark to="./components/FreelanceSignUp"> Sign up as a Freelancer
</v-btn>
<router-view></router-view>
</v-app>
Second change your route name into this one, this route name will be use to call you component itself.
{
path: "./components/CompanySignUp",
name: "company_sign_up",
component: CommpanySignUp
},
Lastly in your main, the final structrue is like this
<v-app>
<v-btn dark to="{name:'company_sign_up'}"> Sign up as a Company </v-btn>
<v-btn dark to="{name:'freelancer_sign_up'}"> Sign up as a Freelancer
</v-btn>
<router-view></router-view>
</v-app>
You have your router.js file defined correctly but you never included it in your app. Instead, you initialized another (empty) router in main.js. Just import your router.js and then include it in your initialization of the app.
import router from 'router.js'; <--- your file
new Vue({
router, <--------- apply router
render: h => h(App)
}).$mount("#app");
The last thing left is to define a place for the router components to render. That is accomplished by placing a <router-view> compenent somewhere in your app template.
<template>
<v-app>
<v-btn dark to="./components/CompanySignUp"> Sign up as a Company </v-btn>
<v-btn dark to="./components/FreelanceSignUp"> Sign up as a Freelancer
</v-btn>
<router-view></router-view> <------------- component rendered here
</v-app>
</template>
For maintenance reasons, consider using the name parameter for the :to prop so you can minimize code changes if you ever need to update the path.
How to change Vuetify tabs together with vue-router
I use vuetify tabs and router see eg. How to use Vuetify tabs with vue-router
In this sample exist two child component Foo and Bar.
I would like to change active tab and route from Foo or Bar component .
This is simplified example. I have the standard Vue structure (main.js, App.vue, Foo.Vue, Bar.vue)
I can change only router via this.$router.replace
Thanks.
JS
const Foo = {
template: '<div>Foo component!</div>'
};
const Bar = {
template: '<div>Bar component!</div>'
};
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar },
];
const router = new VueRouter({ routes });
new Vue({
el: '#app',
router,
});
HTML
<v-app dark>
<v-tabs fixed-tabs>
<v-tab to="/foo">Foo</v-tab>
<v-tab to="/bar">Bar</v-tab>
</v-tabs>
<router-view></router-view>
</v-app>
Add the replace directive to your v-tab:
<v-tab to="/foo" replace>Foo</v-tab>
The key is in the question you linked:v-tab is a wrapper for router-link. Adding the replace prop to a router-link tells it to call router.replace() instead of router.push() (from the API Reference).
Building PWA app with VueJS and I have tabs like navigation component. But instead of show/hide content, navigation is done through Vue Router. Side effect of this navigation is "back" button behavior, every navigation action is logged in browser history, after I visit 4 tabs, and if I want to go back to actual page which was before page with tabs, I need to press "back" 4 or more times (depends on how many times I navigated trough tabs).
What I want to do is something like this:
<router-link no-history="true" to="tab1">Tab1</router-link>
<router-link no-history="true" to="tab2">Tab2</router-link>
<router-link no-history="true" to="tab3">Tab3</router-link>
Of course, I don't want to do it globally. If this even possible?
You need to use router.replace.
From Vue Documentation :
It acts like router.push, the only difference is that it navigates without pushing a new history entry, as its name suggests - it replaces the current entry.
In your case, you would just need to add the replace attribute to your router-link tag :
<router-link to="tab3" replace>Tab3</router-link>
You can find more informations about replace on Vue programmatic navigation doc
add replace to your router-link to avoid stacking routes on the navigation history :
Vue.config.productionTip = false;
Vue.config.devtools = false;
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
const router = new VueRouter({
routes
})
const app = new Vue({
router
}).$mount('#app')
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<h5>Navigate between routes then click "previous"</h5>
<button #click="$router.go(-1)">Previous</button>
<p>
<router-link to="/foo" replace>Go to Foo</router-link>
<router-link to="/bar" replace>Go to Bar</router-link>
</p>
<router-view></router-view>
</div>
The app works fine on every browser, but when I "Add it to my Home Screen" on my iPad, it loads only the "main" component but none of the children.
Here's my main.js :
import Vue from 'vue'
import router from './router'
import App from '#/App.vue'
Vue.config.productionTip = false
const app = new Vue({
router,
render: (h) => h(App)
}).$mount('#app')
My App.vue :
<template>
<div id="app">
<div class="bg">BEFORE VIEW</div>
<router-view class="view"></router-view>
<div class="bg">AFTER VIEW</div>
</div>
</template>
<script>
require('./assets/styles.css')
</script>
My router/index.js :
import Vue from 'vue'
import VueRouter from 'vue-router'
import Parent from '#/components/Parent'
Vue.use(VueRouter)
export default new VueRouter({
mode: 'history',
base: __dirname,
routes: [
{ path: '/', component: Parent },
{ path: '/products',
component: Parent
},
{ path: '/clients',
component: Parent
},
{ path: '/verticals',
component: Parent
}
]
})
and the components/Parent.vue :
<template>
<div class="parent">
<p>INSIDE PARENT</p>
</div>
</template>
<script>
export default {
name: 'Parent'
}
</script>
Basically this is meant to be a kind of slide show, the Parent component will detect the current Route and go to the appropriate slide.
As I mentionned, the app works very well both on my desktop (on Chrome) and on my iPad (on Safari), but when I do "Add it to my home screen", all I see are the "BEFORE VIEW" and the "AFTER VIEW" from the App.vue (and the #app element has the right background color) but everything in the just doesn't load.
I feel like an idiot, I'm sure the solution just depends on a tidbit of knowledge I'm missing, but I can't seem to find anyone else with a problem close enough to mine that I can use their solution.
Please help, thank you so much for your time !
I randomly found a solution that makes the desired content appear.
In router/index.js, I removed the line
mode: 'history',
I honestly don't understand yet why it worked, but it does. I'll look further.
Thanks to everyone who took a look at my problem !