Make header available on all components except on login - javascript

Supposed I am importing a header component on layouts/default.vue
<template>
<div>
<b-container class="mt-5">
<b-row>
<b-col md="6" class="mb-3">
<Header />
</b-col>
<b-col md="6">
<nuxt />
</b-col>
</b-row>
</b-container>
<Header/>
<nuxt/>
</div>
</template>
<script>
import Header from "#/components/Header.vue";
export default {
components: {
Header
}
};
</script>
<style>
...
</style>
and that header will be render on all components.
My question is how can I make the header available on all components except on my Login.vue?
Any idea on where can I start to achieve this.

Solved by reading the documentation on https://nuxtjs.org/guide/views/ layouts section. I created another layout file on layouts folder login.vue and use it on my main login.vue
export default {
layout: 'login' // coming from layouts folder
// page component definitions
}

The current route path is '$route.path',so use 'v-show' to judge.

Related

How to dynamically inject components/fields into a dummy page using vue js?

I am trying to create a dummy vue page, were the different components used in the page like b-field ,b-table etc should be injected into the page in order to make things more dynamic. Currently the fields and components are defined in the template section of the .vue page.
<template>
<div class="container is-fluid">
<b-loading :is-full-page="true" :active.sync="this.isLoading"></b-loading>
<p class="subtitle">Business Unit</p>
<b-field label="Business Unit">
<b-input
required
:disabled="this.newRecord ? false : true"
:value="this.objectData.id"
#input="(newValue)=>{updateValue(newValue,'id')}"
></b-input>
</b-field>
<b-field label="Description">
<b-input
:value="this.objectData.description"
#input="(newValue)=>{updateValue(newValue,'description')}"
></b-input>
</b-field>
<b-field label="Short Description">
<b-input
:value="this.objectData.shortdescription"
#input="(newValue)=>{updateValue(newValue,'shortdescription')}"
></b-input>
</b-field>
<b-field label="Status">
<b-autocomplete
:value="this.objectData.status"
:open-on-focus="true"
:keep-first="true"
:data="['Active','InActive']"
#input="(newValue)=>{updateValue(newValue,'status')}"
></b-autocomplete>
</b-field>
<section>
<p class="is-size-7 has-text-danger">{{submitError}}</p>
<b-button #click="submitForm" class="is-radiusless">Submit</b-button>
<b-button type="is-text" #click="$router.go(-1)" class="is-radiusless">Return</b-button>
</section>
</div>
</template>
<script>
import { viewMixin } from "../viewMixin.js";
const ViewName = "BusinessUnitDetail";
export default {
name: "BusinessUnitDetail",
mixins: [viewMixin(ViewName)],
};
</script>
But the components mentioned in the template section should actually be stored as a string and going forward in the future this string will be retrieved from the database instead. But for the time being and as a starting point , this string can be hardcoded in the script section itself. Now i need a solution or guidance on how to achieve this and make the page to actually work..
Note: Please note that in vue js, i know that we could show or hide components based on the application state using Vue conditional structures such as v-if and v-else. But this is not what iam talking about. Instead i want the components (b-field,b-table etc) to be dynamically injected into the DOM. So in future if there will be an extra b-field or any other component, i can simply append the component tag to the string and that new component will be rendered in the frontend successfully.Plz help?
I guess the solution you look for is vue dynamic components.
So you can do this:
<template v-for="(item, index) of components" :key="index">
<component :is="item.name" :any-prop="item.anyProp">
</template>
...
<script>
// ...
data() {
return {
components: [
{ name: 'b-field', anyProp: 'status' }
]
}
}
</script>

v-app not showing page layout using vuetify

I am using vuetify version 2.3.10. I have a file with layout somewhat like this
<template>
<v-app>
<div>
<Users />
</div>
</v-app>
</template>
<script>
import Users from 'views/users.vue';
export default {
components: {
Users
},
</script>
But "Hello" doesn't show on the browser. But if I remove the tag something like this.
<template>
<div>
<Users />
</div>
</template>
Then in the browser I am getting this error. Cannot read property 'mobileBreakpoint' of undefined. Please help me resolve this issue.
users.vue(component)
<template>
<div>
<p>Hello</p>
</div>
</template>
index.js
The issue was here. I forgot to add vuetify : new Vuetify(), and the issue is resolved.
import Vue from 'vue';
import Vuetify from 'vuetify';
Vue.use(Vuetify);
new Vue({
vuetify : new Vuetify(),
...
});
In your Users component there should be an export default statement as well (without it you can't import it later) and give it the name: 'Users' for good measure as well. Then it should work as intended. Better also store your components in components. views are meant for everything that has an own route.
Users.vue
<template>
<div><p>Hello</p></div>
</template>
<script>
export default {
name: 'Users',
}
</script>
Other.vue
<template>
<v-app>
<div>
<Users />
</div>
</v-app>
</template>
<script>
import Users from '#/components/users.vue';
export default {
components: {
Users
},
</script>
I am in a process of migration of vuetify version 1.5 to 2.3 like you
in my case,
contains minus z-index
check your style sheet

Vue.js - hide a text on a page passed from App.vue

I am really new to Vue. I have multiple pages such as App.vue, Waiting.vue, Reference.vue, Switch.vue and so on. The text defined on **App.vue** is passed along to other pages correctly. But now I dont want to display WELCOME text passed from App.vue to Waiting.vue page. Is there a way that I can hide WELCOME from Waiting.Vue page only?
App.vue
<div id="app">
<b-container>
<b-col lg="5">
WELCOME
</b-col>
</b-container>
</div>
Waiting.vue
<div id="app">
<p class="teamTitle">TEAMS ON DECK</p>
</div>
Ouput for Waiting.vue
WELCOME
TEAMS ON DECK
Let suppose that the Waiting page path is /waiting so you should do :
<div id="app">
<b-container>
<b-col lg="5" v-if="$route.path!=='/waiting'">
WELCOME
</b-col>
</b-container>
</div>
I am assuming that App.vue is acting as parent component and has content that is visible in the page. That being the case, there are multiple ways of hiding information.
If you use a router and Waiting.vue is on a distinct route you can check for route params to selectively hide text. For e.g. in App.vue.
<b-col lg="5" v-if="!this.$route.fullPath === '/waiting'">
WELCOME
</b-col>
If you use global storage like Vuex, just set a variable within Vuex when Waiting.vue is loaded and set the variable to something else in other components
If you are having everything on a single page for any reason, pass a variable as prop and selectively hide the element (similar to [1])
App.vue
<Waiting :hide="true"/>
Waiting.vue
<b-col lg="5" v-if="!hide">
WELCOME
</b-col>
<!-- other code -->
<script>
export default {
props: {
default: false,
type: Boolean,
required: false
}
}
</script>

Vue component unknown despite being registered

I am trying to compose a component inside another like this:
<prompt :users="users">
...
<dataset v-for="ds in users" :user="user"></dataset>
...
</prompt>
But apparently I'm not registering it properly:
[Vue warn]: Unknown custom element: <dataset> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
(found in root instance)
Here's how I'm trying to register it:
app.js
Vue.component('prompt', {
props: ['userdata', 'users'],
template: '#prompt-template',
components: {
'dataset': {
props: ['userdataset', 'user'],
template: '#dataset-template',
}
}
});
Finally, the templates:
<template id="dataset-template">
<li>{{ user}}</li>
</template>
<template id="prompt-template">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" #click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</template>
Are there any steps I'm missing? I can't figure out how the component isn't being registered.
The problem is that you use the dataset component as a slot within the prompt component. While the Vue vm tries to figure out the component tree it will recognize the dataset component which it does not know. Subcomponents are used in the component template but not within slots. You have to register the dataset component within the Vue vm like you did for the prompt component. Try this
Vue.component('promp', { ... })
Vue.component('dataset', { ... })
It also make sense to register the components on the same level since the templates of the components are also registered on the same level (next to each other).
Compare it to the example you mentioned in another answers comment: Here the subcomponent axis-label is only used within the template of the parent polygraph component. This is valid since now the component is in contract to figure out it sub components not the vue-vm.
In other words:
It should be possible to pass components into the slot of any component A which are not subcomponents of A. Therefore all components passed to slots of a component should be available to the vue vm.
Thumb rule could be
if a component does not appear within another components template, it is not a subcomponent.

Components and Slots approach

I have actually 2 global components one for Admin and other one for Modal. The Admin component have a child comp called Page and the Page comp have others childs. I want to pass content directly to Page comp via slots. Like this:
app.js
new Vue({
el: '#app',
components: { Admin, Modal }
})
Admin.vue
<template>
<div>
<page>
<slot></slot>
</page>
</div>
</template>
export default {
components: { Page }
}
Page.vue
<template>
<div>
<page-header>
<slot name="page-header">
<h1 class="page-title">
<slot name="page-title">
Page Title
</slot>
</h1>
</slot>
</page-header>
<page-body>
<slot>
Page Body
</slot>
</page-body>
<page-footer>
<slot name="page-footer">
Page Footer
</slot>
</page-footer>
</div>
</template>
export default {
components: {
pageHeader,
pageBody,
pageFooter
}
}
index.html
<admin>
<div slot="page-header">
Header Test
</div>
Body Test
<div slot="page-footer">
Footer Test
</div>
</admin>
I don't need to use Page as global component, Please any idea?? Hope you understand what I'm looking for...
Thanks
I don't think slots are designed to do this. If you need data to be persisted between parent and children then use either props as #Belmin Bedak suggested. When you pass a prop to a component it will be available to all its children.
If you need to persist state on front-end I strongly recommend using Vuex as source of data for all components ( only use if it becomes more complex to have data scattered across components ).

Categories

Resources