How to place component in the header with lazy loading? - vue.js

In my vue application, how to place component (slot?) in the toolbar component?
My app for example:
<template>
<toolbar>…</toolbar>
<router-view />
</template>
and all the routes are lazy loaded.
for some routes I want to place component inside toolbar component. But I can't "insert" the component as slot. and to write the component and turn on/off with v-if seems to me wrong.
I think that I expect is
<div for="toolbar">This content should in toolbar</div>
<div for="router-view">This content for router-view</div>
Is there any way to solve this?

Vue Router Named Views will come in handy.
Sometimes you need to display multiple views at the same time instead
of nesting them, e.g. creating a layout with a sidebar view and a main
view. This is where named views come in handy. Instead of having one
single outlet in your view, you can have multiple and give each of
them a name. A router-view without a name will be given default as its
name.
A view is rendered by using a component, therefore multiple views require multiple components for the same route. Make sure to use the components (with an s) option:
<template>
<toolbar><router-view name="toolbar"></router-view></toolbar>
<router-view />
</template>
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: YourAwesomeComponent,
toolbar: YetAnotherAwesomeComponent
}
},
{
path: '/home',
components: {
default: YourAwesomeHomeComponent,
toolbar: YetAnotherAwesomeComponentThatSouldBeInToolbarOnHomePage
}
}
]
})

Related

Using nuxt-child's layout instead of the parent's

I am using Nested Routes and <nuxt-child> with layouts on nuxt.js.
The parent is holding the <nuxt-child> component, which is viewing the parent's subroutes.
I want Nuxt to use the parent's layout whenever I'm on its route / subroutes, though if any child has its own layout, I want Nuxt to use it instead of the parent's for it and its subroutes.
My file arrangement is as such:
pages/
--- parent/
------ child.vue
--- parent.vue
layouts/
--- parentLayout.vue
--- childLayout.vue
pages/parent.vue
<template>
<nuxt-child />
</template>
<script>
export default {
layout: "parentLayout",
};
</script>
pages/parent/child.vue
<template>
<span>child.vue</span>
</template>
<script>
export default {
layout: "childLayout",
};
</script>
So based on this example:
I want Nuxt to use the layout 'parentLayout' whenever I'm on the parent/ route or subroutes, though I want to show a different layout - 'childLayout' whenever I'm on parent/child or its subroutes.
The issue is, even if I go to parent/child, the layout that is being used is 'parentLayout' and not 'childLayout', which is because I am using <nuxt-child>.
I have tried using this.$nuxt.setLayout(), but Nuxt still seems to load the parent's layout first, which makes the rendering look off.
How do I overcome this issue and use the wanted layout for child.vue and it's subroutes?
A solution for this is to conditionally set layout in the parent.
export default {
name: 'Parent',
layout ({ route }) {
if (route.name === 'parent-child-id') {
return 'childLayout'
}
return 'parentLayout'
},
data () {
return {}
}
}

How to exit <nuxt-child> when using sub routes

So I have three pages in my app. In my folder structure, I have something like this:
/verify
---complete.vue
---business.vue
---personal.vue
verify.vue
so basically verify.vue has a <nuxt-child> component that deals with my business.vue and personal.vue. What I want to happen is complete.vue even inside the parent route of /verify/complete, will be having a different layout/page template.
Is there any way to achieve this? Thanks.
I was able to fix the problem with extendRoutes in nuxt.config.js. What this does is it adds a custom route without using the folder structure. So when the /verify/complete is hit, it will resolve the component.
router: {
middleware: ['auth'],
base: '/beta/',
extendRoutes(routes, resolve) {
routes.push({
name: 'verify-complete',
path: '/account/verify/complete',
component: resolve(__dirname, 'pages/account/verify-complete.vue')
})
}
}
The idea is to track current route through $route.fullPath, and if i'ts /verify/complete, then change layout appropriately. Lets consider this markup:
verify.vue:
<template>
<section>
<h1 v-if="$route.fullPath === '/verify/complete'">Complete</h1>
<h1 v-else>Business or Personal</h1>
<nuxt-child></nuxt-child>
<section>
</template>
If it's more complicated thah changing some block, tha you should define different pages components, and load them appropriately throug <component :is="COMPONENT_NAME">:
verify.vue:
<template>
<component :is="COMPONENT_NAME"></component>
</template>

I have a question about the app.vue file in vue

In vue, if you declare in a file named app.vue as below, the contents of text.vue will be applied to all pages. By the way, I do not want that text.vue to be applied on certain pages. Is there a way?
app.vue
<template>
<div>
<test></test>
</div>
</template>
You can make use of v-if to conditionally show certain components depending on the page.
You haven't given any details about how your pages are organized, but assuming you are using vue-router and your routes are set up something like this:
router.map({
'/page_one': { name: 'pageOne', component: PageOneView },
'/page_two': { name: 'pageTwo', component: PageTwoView },
});
Then you can add v-if on your component to check the current route's name:
<template>
<div>
<test v-if="['pageOne'].indexOf($route.name) > -1"></test>
</div>
</template>
The array provided to the code above represents the routes on which you would like to hide the component (you can change the comparison logic to only show the component on routes you specify, if you would like the component to be hidden on the majority of routes).

Vue render component as modal in specific route if route metadata key is set to true

I'm using vue-router and i'm trying to create a functionality as follows:
I want to be able to specify in the router routes if a component should be rendered in modal or not. And if it is rendered in Modal keep every component below ( under modal-mask ) as it was.
I've created a modal-wrapper component that have basic modal structure and slot inside its modal body so the component I want to render should go in the slot. But how to achieve that. Does Vue-Router have options for that functioanlity.
Router routes:
{
path: '/customers/:clientId',
component: customerView
meta: {
auth: true,
},
},
{
path: '/customers/:clientId/addAddress',
component: dataViewAdd
meta: {
openInModal: true,
auth: true,
},
},
Since if component should be rendered inside modal while overlaying the previous router-view, I guess ill need 2 router-views.
<router-view class="normal-view"></router-view>
<router-view class="modal-view" name="modal-view"></router-view>
If the component displayed in each modal route was not used in a non-modal context, then you can just modify the modal route component's template (dataViewAdd) so that the modal component is the root of the template. But you mentioned that you would be reusing these components in different situations (so one route might use dataViewAdd inside a modal and another route might use dataViewAdd not inside a modal).
You could create wrapper modal versions of each component, but that'll become messy; it looks like you just want to be able to specify openInModal: true and have it work for any component.
You also mentioned that the position of the modal in the DOM doesn't matter (otherwise I'd recommend using something like portal-vue to assist with this).
First you'll need to change your router configuration so that the modal route is a child of the component you want to keep visible underneath it. Make sure customerView has a <router-view> inside it.
Create a helper function which returns a modal-wrapped version of the component and use that as the route component. This doesn't use the openInModal meta property, but it works in a similar way.
The following code is untested.
import Modal from './modal.vue';
function wrapInsideModal(childComponent) {
return {
functional: true,
render(h) {
return h(Modal, [h(childComponent)]);
},
};
}
// Routes
{
path: '/customers/:clientId',
component: customerView,
meta: {
auth: true,
},
children: [
{
path: 'addAddress',
component: wrapInsideModal(dataViewAdd),
},
],
},

Vue js router-view selection

I have parent component which has
<router-view></router-view>
Inside of parent component there is another component and it also has a
<router-view></router-view>
Both are bound to /login route
When I go to /login route it loads both of them. I would like to skip first/parent router-view for loading the component.
How can i achieve this? I can think of setting some state and prevent loading with v-if directive but that seems kind of wrong.
Maybe another solution, can i pass null to a parent named view on specific route?
Found a solution in case of somebody needs:
<-- applies only this one -->
<router-view name="login"></router-view>
<router-view></router-view>
const router = new VueRouter({
routes: [
{
path: '/',
components: {
login: LoginComp
}
}
]
})
Ref : https://router.vuejs.org/en/essentials/named-views.html