Excluding the nav bar on certain pages in Meteor - authentication

I'm trying to create a meteor app where the login page shows nothing but my Welcome text and a sign in through Google. On my other pages I have a navbar. How do I exclude the navbar specifically from this login page? Does it have to do with iron:router? Is there some sort of special method that I call?

You can make 2 layouts like this.
<template name="layout">
<!-- Regular Stuff for the other pages You can place the navbar here -->
{{> yield}}
</template>
<template name="layoutLogin">
<!-- Just Login Pages -->
{{> yield}}
</template
Now the Javascript Code.
Router.map(function () {
this.route('home', {
path: '/',
layoutTemplate: 'layout'}
);
});
//Here we tell to render the template login, on the path /login and use the content on the layoutLogin
Router.map(function () {
this.route('login', {
path: '/login',
layoutTemplate: 'layoutLogin'}
);
});
Tell me if works.

You can create the template just for navbar and include it wherever required
<template name="top_navbar">
<!--your navbar code -->
</template>
<template name="mypage">
{{> top_navbar}}
<!-- rest of code for my page -->
</template>
<template name="mylogin">
<!-- rest of code for login page -->
</template>

I set up the two templates and then used the following which worked! The primary layout is the one with the navigation bar and the welcome layout is the one without it.
Router.configure({
layoutTemplate: 'primaryLayout'
});
Router.route('/', {layoutTemplate: 'welcomeLayout'});
Thank You!

There is much easier solution to your problem, just set layoutTemplate to null for your particular page that you want the nav and other layout to be excluded. In this case we will exclude the navigation for the login page:
Router.route('login', {
layoutTemplate: '' //the default template is set to null using ''
});

Related

How to embed LinkedIn Profile in VueJs Component

I am using VueJS to build a website and I got to the point where I want to include my embedded profile into a page/Component in Vue. It seems to work only if I refresh the page. When I navigate from other pages to this page it is not displayed.
In my public/index.html I included LinkedIn Library Script
<script type="text/javascript" src="https://platform.linkedin.com/badges/js/profile.js" async defer></script>
In my component:
<template>
<!-- some other code -->
<div class="col-md-4 col-sm-12 text-sm-center">
<div class="LI-profile-badge" data-version="v1" data-size="medium" data-locale="en_US" data-type="vertical" data-theme="dark" data-vanity="nicolae-orlov">
</div>
</div>
</template>
I saw some info that I need to reload the component to force it to re-render but I am not sure how. Any help is much appreciated.
If you want to add a script tag only on a specific component, you can use PostScribe to render a script after load.
After installing (npm i postscribe --save) and importing (import postscribe from 'postscribe'), you can add your script tag in the mounted lifecycle hook:
mounted() {
postscribe('#linkedin', '<script src="https://platform.linkedin.com/badges/js/profile.js"><\/script>')
}
where #linkedin refers to the ID of your profile badge element (add an ID if necessary)
Your linkedin badge should now be embedded in your Vue component.
You can add the javascript by injecting script into head and then adding the html into the respective component. This is how you can inject javascript directly into head from the component.
<script>
export default {
head(){
return{
script : [
{
src:
'https://platform.linkedin.com/badges/js/profile.js',
type:
'text/javascript'
}
],
}
}
}
</script>

Where to put VueJS components common across the application

In my nuxtjs application, I have few features that are used across the application viz Login/Signup dialog, a snackbar to show alerts etc. Since, I want these features on every page and v-app-bar component is already added to all the pages. I have included the components for these features inside v-app-bar component.
<template>
<v-app-bar app id="app-bar">
<LoginJoinDialog />
<AlertSnackbar />
<!-- Code for App bar -->
</v-app-bar>
</template>
But I am not happy with this approach for following reasons
I know these common components does not belong to the v-app-bar component. And just for the sake of DRY and maintenance headaches I have included them. So from design perspective this is not very intuitive.
Secondly, What if in future I have pages that do not have a v-app-bar component. In that case I will be repeating code for these common components anyway. So, the pain of maintaining the code at multiple places will still be there.
Considering the above points, I am looking for a more elegant approach than what I have implemented. If there is a vuejs recommendation on this, even better. What suggestions do you have for component structuring for these common features?
You can acheive what you are looking for using layouts. What you need to do is make layouts folder inside src directory. And then you can create as many
layout components(*.vue files) and use them as you like.
For an example, this is default.vue component inside layouts folder:
<template>
<main>
<!-- Your app bar component -->
<v-app-bar app id="app-bar">
<LoginJoinDialog />
<AlertSnackbar />
<!-- Code for App bar -->
</v-app-bar>
<!-- Page Content (This tag will automatically embed the page content into layouts)-->
<nuxt />
</main>
</template>
<script>
export default {};
</script>
Now, on your pages folder, you can add index.vue file where you can reference the default layout, as a property in this manner: layout: 'default'
The index.vue file should look something like this:
<template>
<!-- page content goes here -->
</template>
<script>
export default {
name: 'HomePage',
layout: 'default',
};
</script>
I also have created an example project in nuxt with layouts.
For a working prototype of the project: Visit this link.
I hope it helps to solve your issue.
You can use global component registration trick by Chris Fritz. You just to need to modify it a bit so it's more fitting for a nuxt.js app. So you can create a base folder under your components folder and keep all these shared components there. Then create a new plugin and change the path to your #/components/base folder and modify the regex so it grabs all the files, no matter what the name is:
globalComponents.js
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
export default () => {
const requireComponent = require.context(
'#/components/base', false, /[\w-]+\.vue$/
)
requireComponent.keys().forEach(fileName => {
const componentConfig = requireComponent(fileName)
const componentName = upperFirst(
camelCase(fileName.replace(/^\.\/(.*)\.\w+$/, '$1'))
)
Vue.component(componentName, componentConfig.default || componentConfig)
})
}
nuxt.config.js
plugins: [
'~/plugins/globalComponents.js'
],

How to implement the navigating action of right click menu in Vue?

I am building a demo app, used for handling data. There is a lot of actions available. So I decide to implement a quick menu, which navigate the user to the detail panel, using the right click menu.
I try to use vue-router to mark all function with a unique path, like /action/info, /action/merge. But it turns out to be lack of management.
Are there any good way to solve it?
Vue-router makes sense to use if your actions demand a full screen. Otherwise, you can use a simple dialogue. But if you don't want to consider each action as a separate page, I see two options:
Option 1: You can use full-screen dialogues: you can show them without changing the route.
Option 2: You can use alternative navigation component that navigates without routes. It's not necessary to use it for the whole app. You can use it only for the page where you call all your actions. For example, take a look at v-ons-navigator from Onsen UI. It doesn't use routes, but a stack:
// Go to the "main" page by Vue-router and use v-ons-navigator inside to navigate
// between actions.
<template id="main">
<v-ons-navigator swipeable
:page-stack="pageStack"
#push-page="pageStack.push($event)"
></v-ons-navigator>
</template>
<template id="page">
<v-ons-page>
<v-ons-toolbar>
<div class="center">Page</div>
</v-ons-toolbar>
<p style="text-align: center">
This is the page
<v-ons-button #click="push">Action!</v-ons-button>
</p>
</v-ons-page>
</template>
<template id="action">
<v-ons-page>
<v-ons-toolbar>
<div class="left">
<v-ons-back-button>Page</v-ons-back-button>
</div>
<div class="center">Action!</div>
</v-ons-toolbar>
<p style="text-align: center">This is the page of the action</p>
</v-ons-page>
</template>
const action = {
key: 'action',
template: '#action'
};
const page = {
key: 'page',
template: '#page',
methods: {
push() {
// Here you go to the page of your action.
// You just push it in the stack without changing the route.
this.$emit('push-page', action);
}
}
};
const main = {
template: '#main',
data() {
return {
pageStack: [page]
}
}
};

Vue component not rendered on second visit

I have a Vue component that lists a bunch of clickable tags. When you click on a tag, it takes you to another page with a list of objects containing that tag.
The relevant parts of the component code are:
<template>
<div>
<h2>All Tags</h2>
<TagList v-bind:tags="tags"/>
</div>
</template>
...
<script>
import TagList from './TagList'
export default {
name: 'AllTags',
components: {
TagList
},
data () {
return {
tags: []
}
},
mounted () {
tags = // array loaded from a database
}
}
</script>
This all works fine when I initially view the page. However if I browse away from this list, e.g. by clicking on a single tag, and then browse back, I only see the <h2>All Tags</h2> header. Using the Vue debugger in the browser, I can see that the data are still there.
I'm using <router-view :key="$route.fullPath"> to control the overall app and suspect the problem lies with the keys somehow.
Can someone point me in the right direction here? How can I get the TagList component to render every time I visit that page of the app?
EDIT: Here's the code of the TagList component:
<template>
<div class="tags">
<Tag v-for="tag in tags" v-bind:tag="tag" v-bind:key="tag" />
</div>
</template>
<script>
import Tag from './Tag'
export default {
name: 'TagList',
props: ['tags'],
components: {
Tag
}
}
</script>
You can try removing v-bind all thought its not required to use, I've checked your code it seems to work fine after visiting a tag and going back, all tags are still rendered. You can take a look at this working sample .
https://codesandbox.io/s/vue-template-3tcs4?fontsize=14

How to stop <router-link> from sending the user to another page?

I have a logic like this: is the user is V2 use the user to the url in subHeaderRouter.router. If the user isn't launch this.openModal:
<router-link
v-for="subHeaderRouter in subHeaderRouters"
:to="subHeaderRouter.router"
#click="handleOpenModal()">
</router-link>
handleOpenModal () {
if (this.IsV2User) return
this.openModal('changeUserType', 'user.changeUserType')
}
The only thing I need to do now is to stop :to then she user is not V2. How to accomplish that?
You can prevent the default <router-link> behavior by specifying no default event to listen to and handling the click event manually with the .native modifier:
<router-link
v-for="subHeaderRouter in subHeaderRouters"
event=""
:to="subHeaderRouter.router"
#click.native.prevent="handleOpenModal(subHeaderRouter.router)"/>
handleOpenModal(route) {
if (this.IsV2User) {
this.$router.push(route)
} else {
this.openModal('changeUserType', 'user.changeUserType')
}
}
If the event="" seems weird to you, it also works with an empty attribute:
<router-link
v-for="subHeaderRouter in subHeaderRouters"
event
:to="subHeaderRouter.router"
#click.native.prevent="handleOpenModal(subHeaderRouter.router)"/>
Vue 3 Solution
In Vue3, the event has been removed from "<router-link>, you will need to use v-slot API instead.
<router-link :to="yourRoute" custom v-slot="{ href, navigate }">
<a v-if="yourBoolean" #click="handleEvent()">Run the function</a>
<a
v-else
:href="href"
#click="navigate">
Go to route in "to"
</a>
</router-link>
// Vue 3 Composition API
export default {
setup() {
const handleEvent = () => {
// Add your logic here
}
}
};
I had the same problem and used dynamic Vue Components as solution. You will also have to check the difference in styling for router and div tag.
<component
:is=" condition ? 'router-link' : 'div' "
#click="handleOpenModal"
:to="your_link">
</component>