How to show login page outside the layout using vue js 3? - vuejs3

I want to show login page outside the layout but unfortuntly i see the sidebar and header on login page sidebar and header should not be on login page please help me how can i resolve that thank u ?
App.vue
<script setup>
import { RouterLink, RouterView } from 'vue-router'
import Layout from './components/Layouts/Layout.vue'
</script>
<template>
<div id="app">
<Layout></Layout>
</div>
<RouterView />
</template>
<script>
export default {
name: 'App',
components: {
Layout,
}
}
</script>
router\index.js
import { createRouter, createWebHistory } from 'vue-router'
import Login from '../views/Login.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'login',
component: Login
},
{
path: '/dashboard',
name: 'dashboard',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/DashBoard.vue')
},
]
})
export default router

Use conditional rendering to hide/show elements based on the current route
<Layout v-if="route.path !== '/'"></Layout>
<script setup>
import { RouterLink, RouterView, useRoute } from 'vue-router'
import Layout from './components/Layouts/Layout.vue'
const route = useRoute();
</script>
Also, not sure why you have two script tags. You don't need to register components with the Composition API (script setup), so you can/should remove the second script

Related

Not able to fetch url params in vue js

Hi I am trying to fetch the value for "customerID" and "iot" in MyIOT.vue. When I enter the url http://localhost:8080/5/345435 it gives me an empty value for params. I tried both ways using routing and props. None of them is working. Not sure where I am getting it wro
main.js
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'
import MyIot from './components/MyIOT.vue'
//import router from './router/index.js'
const routes = [
// {
// path: '/',
// redirect: '/:customerID/:iot'
// },
{
path: '/:customerID/:iot',
component: MyIot,
//props: true,
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
const app = createApp(App).use(router);
app.mount('#app');
App.vue
<template>
<MyIot />
</template>
<script>
import MyIot from './components/MyIOT.vue'
//import axios from "axios";
export default {
name: "App",
components: {
MyIot,
},
};
</script>
components/MyIOT.vue
<template>
<div>customer id is: {{customerID}} and iot is : {{iot}}
</div>
</template>
<script>
import { useRoute } from 'vue-router'
export default {
name: 'MyIot',
//props: ['customerID', 'iot'],
setup() {
const route = useRoute();
console.log(route.params);
}
}
</script>

router-link won't load page

Can't find what I am doing wrong. If I type the url on the browser the page does load, but the links from the navbar do nothing. I am trying three different ways to use router-link, but makes no differences. It just won't render the page via link. No errors on the console. On the vue devtools the routing displays the correct path.
App.vue:
<template>
<nav class="navbar">
<router-link :to="{ path: '/' }">Home</router-link>
<router-link :to="{name:'TheDashboard'}"> Dashboard</router-link>
<router-link to="/games">Games</router-link>
</nav>
<router-view></router-view>
</template>
router/index.js:
import { createRouter, createWebHistory } from 'vue-router'
import TheHomePage from '#/pages/TheHomePage'
import TheDashboard from '#/pages/TheDashboard'
const routes = [
{
path: '/',
name: 'TheHomePage',
component: TheHomePage
},
{
path: '/dashboard',
name: 'TheDashboard',
component: TheDashboard
},
{
path: '/games',
name: 'TheGames',
component: () => import(/*webpackChunkName: "games" */ '#/pages/TheGames.vue'),
props: true
},
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
main.js:
import { createApp } from 'vue'
import App from '#/App.vue'
import router from '#/router'
import store from '#/store'
const prototype = createApp(App)
prototype.use(router)
prototype.use(store)
prototype.mount('#app')
In the end this was a bug caused by Vue devtools. I removed previous versions and updated to latest, and it is now working. Nothing wrong with the code. I thought I might as well leave the code here, since it might be helpful for other people.
your code seems optimal to me. However, you can use the beforeEach and afterEach hooks to help you to debug your App.
you can read about them here
do something like:
//router/index.js
//...
//const router = ...
router.afterEach((to, from, failure) => {
console.log('to: ', to);
console.log('from: ', from);
if (isNavigationFailure(failure)) {
console.log('failed navigation', failure)
}
});
export router;

Cypress component test with NextJS useRouter function

My Navbar component relies on the useRouter function provided by nextjs/router in order to style the active links.
I'm trying to test this behavior using Cypress, but I'm unsure of how I'm supposed to organize it. Cypress doesn't seem to like getRoutePathname() and undefined is returned while within my testing environment.
Here's the component I'm trying to test:
import Link from 'next/link'
import { useRouter } from 'next/router'
function getRoutePathname() {
const router = useRouter()
return router.pathname
}
const Navbar = props => {
const pathname = getRoutePathname()
return (
<nav>
<div className="mr-auto">
<h1>Cody Bontecou</h1>
</div>
{props.links.map(link => (
<Link key={link.to} href={link.to}>
<a
className={`border-transparent border-b-2 hover:border-blue-ninja
${pathname === link.to ? 'border-blue-ninja' : ''}`}
>
{link.text}
</a>
</Link>
))}
</nav>
)
}
export default Navbar
I have the skeleton setup for the Cypress component test runner and have been able to get the component to load when I hardcode pathname, but once I rely on useRouter, the test runner is no longer happy.
import { mount } from '#cypress/react'
import Navbar from '../../component/Navbar'
const LINKS = [
{ text: 'Home', to: '/' },
{ text: 'About', to: '/about' },
]
describe('<Navbar />', () => {
it('displays links', () => {
mount(<Navbar links={LINKS} />)
})
})
Ideally, there'd be a provider for Next.js's useRouter to set the router object and wrap the component in the provider in mount. Without going through the code or Next.js supplying the documentation, here's a workaround to mock useRouter's pathname and push:
import * as NextRouter from 'next/router'
// ...inside your test:
const pathname = 'some-path'
const push = cy.stub()
cy.stub(NextRouter, 'useRouter').returns({ pathname, push })
I've added push because that's the most common use case, which you may also need.

Vue 3 extends vue.js components from third party library in defineComponent

I want to use third party library element-plus in my component. In setup defineComponent entends that component. In console, it would warn Failed to resolve component: el-radio at <App>
In about router, Here is the about.vue
<template>
<div id="popup-content"></div>
</template>
<script>
import {
onMounted, createApp, defineComponent, nextTick,
} from 'vue';
import Test from '#/components/Test.vue';
export default {
setup() {
onMounted(() => {
const myNewComponent = defineComponent({
extends: Test,
});
createApp(myNewComponent).mount('#popup-content');
nextTick(() => {
createApp(myNewComponent).mount('#popup-content');
});
});
},
}
Test component has used element-plus el-raido component, Test.vue
<template>
<el-radio v-model="radio" label="1">备选项</el-radio>
<el-radio v-model="radio" label="2">备选项</el-radio>
</template>
<script>
export default {
data() {
return {
radio: '1',
};
},
};
</script>
I have add element-plus, and register all in main.js
import { createApp } from 'vue';
import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
import App from './App.vue';
const app = createApp(App);
app.use(ElementPlus);
app.mount('#app');
I have found this question
Extend vue.js component from third-party library
I really really don't understand what are you trying to achieve by extending your perfectly fine Test component BUT...
Vue 3 is very different from Vue 2 - a lot of global API's (as component registration for example) are not global anymore but are tight to a "app instance" (created by createApp)
So even if you register Element components in main.js (app.use(ElementPlus);), the another app instance (why!?) created in onMounted hook of about.vue component knows nothing about the components! That is the reason for an error...
You must register components in every app instance created by createApp you want to use them in ....
As #Michal Levý answered, I need to register components in every app instance created by createApp.
Here is the working version about.vue, in case someone need.
<template>
<div id="popup-content"></div>
</template>
<script>
import {
onMounted, createApp, defineComponent, nextTick,
} from 'vue';
import Test from '#/components/Test.vue';
import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
export default {
setup() {
onMounted(() => {
const myNewComponent = defineComponent({
extends: Test,
});
const app1 = createApp(myNewComponent);
nextTick(() => {
app1.use(ElementPlus);
app1.mount('#popup-content');
});
});
},
}

Vue.js / Firebase and Vuefire - Read and update a single object

I've been trying to set up a simple app to test some Vue.js features and I've been finding here and there some intersting tutorials about basic CRUD implementation.
I've been stuck on something a little different since a few days, here's a simple description of what I try to achieve :
Set up a home page that displays first and last name.
Store first and last name in firebase as strings
Simply display the two strings on screen
later allow the logged-in user to edit the string (not part of my problem here but relevant to explain why I need the two fields to be stored in Firebase)
I've already worked on a small architecture with login management, different menus for logged in/out states, things like that.
So I already set up that in Firebase :
Firebase configuration
Then here my core files :
main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import firebase from 'firebase'
import VueFire from 'vuefire'
import { store } from './store/store'
let app
let config = {
apiKey: '######',
authDomain: '######',
databaseURL: '######',
projectId: '######',
storageBucket: '######',
messaginSenderId: '######'
}
firebase.initializeApp(config)
firebase.auth().onAuthStateChanged(function (user) {
if (!app) {
/* eslint-disable no-new */
app = new Vue({
el: '#app',
store: store,
router,
template: '<App/>',
components: { App }
})
}
})
export const db = firebase.database()
export const homeContent = db.ref('homeContent')
Vue.config.productionTip = false
Index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '#/components/HelloWorld'
import Test from '#/components/Test'
import Login from '#/components/Login'
import SignUp from '#/components/SignUp'
import firebase from 'firebase'
import VueFire from 'vuefire'
Vue.use(Router)
Vue.use(VueFire)
let router = new Router({
routes: [
{
path: '*',
redirect: '/login'
},
{
path: '/',
redirect: '/login'
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/test',
name: 'Test',
component: Test,
meta: {
requiresAuth: true
}
},
{
path: '/sign-up',
name: 'SignUp',
component: SignUp
},
{
path: '/hello-world',
name: 'HelloWorld',
component: HelloWorld,
meta: {
requiresAuth: true
}
}
]
})
router.beforeEach((to, from, next) => {
let currentUser = firebase.auth().currentUser
let requiresAuth = to.matched.some(record => record.meta.requiresAuth)
if (requiresAuth && !currentUser) next('/login')
else if (!requiresAuth && currentUser) next()
else next()
})
export default router
App.vue
<template>
<div id="app">
<div v-if="user">Logged in</div>
<div v-else>NOT logged in</div>
<Navigation></Navigation>
<button id="btLogout" v-if="user" v-on:click="logout">Déconnexion</button>
<img class="logo" src="./assets/logo.png">
<router-view/>
</div>
</template>
<script>
// Register Navbar component
import Navigation from './components/Nav.vue'
import firebase from 'firebase'
export default {
computed: {
user () {
return this.$store.getters.getUser
}
},
components: {
'Navigation': Navigation
},
methods: {
logout: function () {
firebase.auth().signOut().then(() => {
this.$store.dispatch('clearUser')
this.$router.replace('login')
})
},
setUser: function () {
this.$store.dispatch('setUser')
}
},
created () {
// when the app is created run the set user method
// this uses Vuex to check if a user is signed in
// check out mutations in the store.js file
this.setUser()
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.logo {
width: 50px;
height: auto;
clear: both;
display: block;
margin: 30px auto 0;
}
#btLogout {
clear: both;
display: inline-block;
}
</style>
Test.vue
<template>
<div class="homeScreen">
<p v-bind:key="homeContent['.key']" v-for="firstName of homeContent">{{ homeContent.firstName }}</p>
<p v-bind:key="homeContent['.key']" v-for="lastName of homeContent">{{ homeContent.lastName }}</p>
<img src="../assets/annonce_motw.jpg">
</div>
</template>
<!-- Javascript -->
<script>
import firebase from 'firebase'
import db from "../main"
export default {
data () {
return {
db: ''
}
},
firebase: {
homeContent: {
source: db.ref('homeContent'),
asObject: true
}
},
methods: {
setHomeName (key) {
// homeName.child(key).update({ edit: true })
}
},
created () {
}
}
</script>
<!-- SASS styling -->
<style scoped>
</style>
So here I am. The part where I'm stuck is that everytime I try to add in Test.vue the line db.ref('homeContent') the console returns that db is undefined.
I also can't figure how to simply output the stored strings after resolving the console problem.
So what did I do wrong? :D
Thanks and advance for every piece of help you'll bring! Cheers!
The line
export const db = firebase.database()
gets executed before firebase.initializeApp(config) has finished executing, so it will be undefined.
One way to solve this is to put the initialized Firebase object on the Vue prototype:
Vue.prototype.$firebase = Firebase.initializeApp(config)
Then, inside any of your components, such as Test.vue, you can refer to the Firebase object like this:
firebase: {
homeContent: {
source: this.$firebase.database().ref('homeContent'),
asObject: true
}
},
One caveat: This only works if you create the Vue app after you know Firebase has finished initializing. You did this correctly by putting the new Vue() statement inside firebase.auth().onAuthStateChanged() in main.js, so you will be guaranteed to have an initialized Firebase object available to you at this.$firebase in any of your components.

Resources