Separate login component than handling component Vue.js - vue.js

I am trying to code a mini application with Vue.js. I want to display the login page on the first page if the user is not logged in. Else,
if the user logged in, I want to show a dashboard or a landing page.
I tried it with app.vue.
I test with a variable that I created. It works, but when I log in, I can't get access to any other page. Is there a solution to separate the login page from the landing page?
File App.vue:
<template>
<div v-if="mvar" id="app">
<div>
<Header />
<div class="container-fluid">
<div class="row">
<Sidebar />
<Main />
</div>
</div>
</div>
<notifications />
</div>
<div v-else id="app">
<Login />
<notifications />
</div>
</template>
<script>
import Main from './components/template/TheMain.vue'
import Header from './components/template/TheHeader.vue'
import Sidebar from './components/template/TheSidebarMenu.vue'
// import Login from "./modules/authentication/AuthLogin.vue";
export default {
name: 'App',
components: {
Main,
Header,
Sidebar,
// Login,
},
data() {
return {
mvar: myVar,
}
},
}
</script>

Related

NuxtPage vs slot for Nuxt3

What is the difference between these two components in Nuxt3 and how do I use them correctly?
If I want to use pages/... what is the right approach here to create links and jump from page to page?
Everything is pretty much explained in the documentation: https://v3.nuxtjs.org/migration/pages-and-layouts/
You need to use this in app.vue
<template>
<nuxt-layout>
<nuxt-page /> <!-- used to display the nested pages -->
</nuxt-layout>
</template>
With a default /layouts/default.vue file
<template>
<div>
this is coming from the layout
<slot /> <!-- required here only -->
</div>
</template>
You will get this on / (with /pages/index.vue)
<template>
<div>index page</div>
</template>
And with the following structure, you will achieve dynamic pages
/pages/users/index.vue
<script setup>
definePageMeta({
layout: false
});
function goToDynamicUser() {
return navigateTo({
name: 'users-id',
params: {
id: 23
}
})
}
</script>
<template>
<div>
<p>
index page
</p>
<button #click="goToDynamicUser">navigate to user 23</button>
</div>
</template>
/pages/users/[id].vue
<script setup>
definePageMeta({
layout: false
});
const route = useRoute()
</script>
<template>
<pre>{{ route.params.id }}</pre>
</template>
I've removed the layout here to show how to disable it, but you can totally let the default here or even provide a custom one.
So, nuxt-page is to be used when you want to display the pages in your app (replacing <nuxt /> and <nuxt-child />) while <slot /> is to be used in the layout (as any other component using the slot tag).

Vue how to customize global navbar at view level

Im super new to Vue.
i have a Vue-CLI app, which have a navbar and content.
Navbar is common to all pages, but i want to customize in each page whit some additional content.
Example:
Common-> home | about
View home -> home | about | your are in view home
View about -> home | about | your are in view about
router/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home.vue';
import NavBar from '#/components/NavBar.vue';
Vue.use(VueRouter);
Vue.component('nav-bar', NavBar);
//...
components/navbar.vue
<template>
<div>
<b-nav-item to="/">home</b-nav-item>
<b-nav-item to="/about">about</b-nav-item>
{{customContent}}
</div>
</template>
<script>
export default {
name: 'NavBar',
props: {
customContent: {
type: String,
default: 'default Content',
},
},
};
</script>
App.vue
<template>
<div id="app">
<nav-bar />
<div class="container-fluid">
<router-view />
</div>
</div>
</template>
views/home.vue
<template>
<div class="row">
<div class="col-12">
<image-card :images="images"/>
</div>
</div>
</template>
<script>
//how can i customize here the navbar by adding for example 'your are in view home'???
</script>
Thanks so much!
There are a few ways in which you can solve this problem. I'll list two of them.
1. Update NavBar by $route
In this approach, the NavBar component already contains all of the possible combinations, and will display the relevant portion(s) depending on what $route contains.
Here's some pseudo code:
navbar.vue
<template>
<div class="navbar">
<div class="navbar-left>
APPNAME
</div>
<div v-if="name === 'landing'">
...
</div>
<div v-else-if="name === 'room'">
...
</div>
</div>
</template>
App.vue
<template>
<div id="app">
<NavBar :name="$route.name"/>
<main>
<router-view/>
</main>
</div>
</template>
In this example, the NavBar component is very rigid, and doesn't really lend itself to much reuse. However, it does encapsulate all the relevant code relating to the nav bar.
2. Extensible NavBar with slots
In this approach, the NavBar only provides the bare-minimum to create a nav bar. The rest of the route-specific elements are to be filled in by the views.
navbar.vue
<template>
<div class="navbar">
<div class="navbar-left">
<div class="navbar-brand">
APPNAME
</div>
<slot name="left"></slot>
</div>
<div class="navbar-right">
<slot name="right"></slot>
</div>
</div>
</template>
App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
landing.vue
<template>
<div>
<header>
<NavBar>
<template slot="right">
<span>
<div class="navbar-item">
<div class="buttons">
<button class="button" #click="...">Start Watching</button>
</div>
</div>
</span>
</template>
</NavBar>
</header>
<main>
...
</main>
</div>
</template>
This approach has a bit of repetition in terms of DOM elements, but gives you an extremely flexible NavBar that can be customized by each view.
The approach you want to use depends on what is important to you.
If strict encapsulation is what you want, then you may want to use approach 1, as all of the NavBar-related code is contained within a single file.
However, if you believe that there is a potential for reuse, or if you would like all view-related code to live in one place, then it makes sense to use slots instead and extend the NavBar as required by each view.
I use a breadcrumb to achieve a similar thing. Just an idea but Vue router allows you to add meta data to the current route which you always have access to
router.js
path: '/add',
name: 'add',
component: () => import(/* webpackChunkName: "add" */ '../../views/Add.vue'),
meta: {
breadCrumb: [
{ name: 'Add New' }
]
},
Notice the meta object attached to the route.. this will be used to describe the current view.
Breadcrumb.vue component
<template>
<div class="breadcrumb">
<ul class="d-flex m-0 p-0"
<li
v-for="(breadcrumb, idx) in breadcrumbList"
:key="idx">
{{ breadcrumb.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Breadcrumb',
data () {
return {
breadcrumbList: []
}
},
mounted () { this.updateList() },
watch: { '$route' () { this.updateList() } },
methods: {
routeTo (pRouteTo) {
if (this.breadcrumbList[pRouteTo].link) this.$router.push(this.breadcrumbList[pRouteTo].link)
},
updateList () { this.breadcrumbList = this.$route.meta.breadCrumb },
formatPath(path) {
const newPath = path.replace(/\//g, " > ")
return newPath
}
}
}
</script>
And then you can import the breadcrumb into your navbar or where ever you would like to place it
<Breadcrumb class="breadcrumb" />
import Breadcrumb from '#/components/Breadcrumb.vue'
components: {Breadcrumb}
So basically the breadcrumb will always watch your current route and change the data based on the meta data you provide in your router.js file
You can access to router name like this:
<div v-if="this.$route.name == 'home'">
<HeaderTransparent />
</div>
<div v-else>
<HeaderWhite />
</div>

How to passing the data to another component in vue js

I created a career page which is when user select the title of the position that they apply, it will redirect into application form and it will display the title of the position. If they are interested to apply for the position they will enter some input which is their full name, contact and cv. Once they submitted the application, it will send the data into the server include the position that they already applied.
Header.vue
<template>
<div>
<h1 class="title-wrapper">
Application Form
</h1>
<p class="info-wrapper">
You are applying as
<nuxt-link to="/careers">
<u>{{ title }}</u>
</nuxt-link>
</p>
</div>
</template>
<script>
export default {
name: 'Header',
props: {
title: {
type: String,
default: ''
}
}
};
</script>
Form.vue
<form class="app-form" #submit.prevent="onSubmit">
<InputField
v-model="fullName"
label="Full Name"
firequired
required
placeholder="Your full name"
#handleChange="handleChangeName($event)"
/>
<button type="submit">Submit</button>
</form>
Application.vue (Parent)
<div class="contact-wrapper">
<Intro :title="title" />
<Form />
</div>
The validation for submit the form is inside the Form.vue, how to send the title from Header.vue into Form.vue and send it into the server. This is what I've tried
Form.vue
<script>
export default {
name: 'Submit',
template: '<nuxt-link to="/careers"><u>{{ title }}</u></nuxt-link>',
methods: {
onSubmit() {
this.$axios.post('url', {
position:this.title
})
}
};
</script>
And it returns nothing

Amplify Vue amplify-authenticator component not displaying

I have been using an <amplify-authenticator> component on the Home.vue view of a web application, via the HelloWorld.vue component. This was working as expected, with signedIn state monitored using store.js and Vuex.
I have now switched to routing to Home.vue or Login.vue depending on sign-in state.
However, when a signed out user correctly routes to Login.vue, the page displays as expected, minus the <amplify-authenticator> component. It is clear from the Styles that this is importing (amazonOrange is listed as a color), but for some reason the sign-in interface is no longer displaying correctly.
Login.vue
<template>
<div class="login">
<div>
<vue-headful title="Login"/>
</div>
<div>
<p>
<router-link to="/">Login</router-link> |
<router-link to="/about">About</router-link>
</p>
</div>
<div>
<p><img alt="Vue logo" src="../assets/logo.png" /></p>
</div>
<div>
<amplify-authenticator></amplify-authenticator>
</div>
</div>
</template>
<script>
import { Auth } from "aws-amplify";
import { AmplifyEventBus } from "aws-amplify-vue";
export default {
name: "Login",
props: {
msg: String
}
};
</script>
If I change amplify-authenticator to amplify-sign-in then I see a sign in interface, but this needs additional scripting to implement.
I'd like to know specifically why the Authenticator component isn't displaying, since I cannot see an obvious bug in my code.
Solved. If the user is signed in to Amazon Cognito, then the <amplify-authenticator> will not display. The problem was with a bug in the check on signedIn state, which was redirecting the user to the wrong page.

pass template from a .vue file to another .vue file

I am trying to follow this tutorial. I am getting a Modal using below code.
<modal
v-model="showModal"
:animation-duration="animationDuration"
:close-on-click-away="closeOnClickAway"
>
<p slot="header">Confirmation needed</p>
<p slot="content">Do you want to continue?</p>
<template slot="actions">
<div class="ui black deny button"
#click="showModal=false">
No
</div>
<div class="ui positive right labeled icon button"
#click="confirm">
Yes
<i class="checkmark icon"></i>
</div>
</template>
</modal>
Here I would like to place below portion of the code in another .vue file named ModalBody.vue.
<p slot="header">Confirmation needed</p>
<p slot="content">Do you want to continue?</p>
<template slot="actions">
<div class="ui black deny button"
#click="showModal=false">
No
</div>
<div class="ui positive right labeled icon button"
#click="confirm">
Yes
<i class="checkmark icon"></i>
</div>
</template>
Then I am trying to access that file like below
<modal
v-model="showModal"
:animation-duration="animationDuration"
:close-on-click-away="closeOnClickAway"
>
<modal-body></modal-body>
</modal>
But it is not working. Even I am not getting any error in console.
UPDATE
Parent.vue
<template>
<modal
v-model="showModal"
:animation-duration="animationDuration"
:close-on-click-away="closeOnClickAway"
>
<modal-body></modal-body>
</modal>
</div>
</template>
<script>
import ModalBody from './ModalBody';
export default {
components: { ModalBody },
}
</script>
use import
<template>
<!-- html code -->
<modal-body v-show="showModal"></modal-body>
</template>
<script>
import modalBody from './ModalBody'
export default {
components: {
childComponent
},
data: () => ({ showModal: false })
}
</script>
UPDATE:
I committed mistakes, but your noticed her.
your updated code have mistakes too
tag </div>
<modal> - is a component
so
Parent.vue
<template>
<modal
v-model="showModal"
:animation-duration="animationDuration"
:close-on-click-away="closeOnClickAway"
>
<modal-body></modal-body>
</modal>
</template>
<script>
import ModalBody from './ModalBody';
import modal from './modal';
export default {
components: {
ModalBody,
modal
}
/* component code */
}
</script>
important!
If you want to insert another component or element into the component, then inside this component there must be a <slot></slot>. see
also see my example app: https://codesandbox.io/s/3xyx386q65
open 'components/setProps/setProps.vue'