Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support the use of slot in layout files #190

Closed
dohomi opened this issue Feb 1, 2017 · 40 comments
Closed

support the use of slot in layout files #190

dohomi opened this issue Feb 1, 2017 · 40 comments

Comments

@dohomi
Copy link

dohomi commented Feb 1, 2017

Hello,

it would be nice if slot areas would assignable in layout files. Often parts of the pages need to be rendered inside of the top toolbar. Thanks

This question is available on Nuxt.js community (#c162)
@Atinux
Copy link
Member

Atinux commented Feb 2, 2017

Can you provide an example of what you are trying to do @dohomi ?

@Atinux Atinux added the question label Feb 2, 2017
@dohomi
Copy link
Author

dohomi commented Feb 3, 2017

Hello @Atinux here a simple example to get content into the toolbar and content section of an app

index.vue

<template>
  <div>
    <div slot="toolbar">
      <h2 class="md-title">Welcome to index</h2>
    </div>
    <div slot="content">
      <p>her comes the content...</p>
    </div>
 </div>
</template>

default_layout.vue

<template>
<div>
<header>
  <slot name="toolbar"></slot>
</header>
<content>
  <slot name="content"></slot>
</content>
</div>
</template>

Currently I do this through a custom component and leave the layout file with just the <nuxt/> almost empty.

@Atinux
Copy link
Member

Atinux commented Feb 3, 2017

Hi @dohomi

It's not possible with layouts logic of nuxt.js since it's based on vue-router.

But nothing is impossible with vue.js 😄

You can create a layout folder (without the s) for example where you can create your layouts with slots.

layout/default.vue

<template>
  <div>
    <header>
      <slot name="toolbar"></slot>
    </header>
    <content>
      <slot name="content"></slot>
    </content>
  </div>
</template>

And then, in your pages, you can can import the layout (we use it as <page>) and use the slots:

<template>
  <page>
    <div slot="toolbar">
      <h2 class="md-title">Welcome to index</h2>
    </div>
    <div slot="content">
      <p>her comes the content...</p>
    </div>
 </page>
</template>

<script>
import page from '~/layout/default'

export default {
  components: { page }
}
</script>

@Atinux Atinux closed this as completed Feb 3, 2017
@dohomi
Copy link
Author

dohomi commented Feb 7, 2017

Hi @Atinux thats how I am doing it right now. Thanks for the example and good to know that I did it in the right way.

@dohomi
Copy link
Author

dohomi commented Feb 15, 2017

Hi @Atinux @alexchopin is it somehow possible to use router-view feature of vue-router? In my current setup I would love to render the toolbar directly from page into a separate section of the layout. Similiar approach like above, but currently with using a component for layout the render of specific fields of my layout are rendered again.
Thanks for heads up

@dohomi
Copy link
Author

dohomi commented Feb 15, 2017

never mind... I got it working with tweaking the css and now the structure respects. Still there might be some workflows where router-view support would be beneficial for the developers.

@Etheryte
Copy link

vue-router supports named views out of the box, it's very unclear why Nuxt is limiting the usage as it is. Named views and/or slots offer a much more diverse approach to composition and there's no reason to support them only through workarounds.
From vue-router docs:

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})

@easherma
Copy link

easherma commented Jul 6, 2018

Any updates on this with current/forthcoming versions?

@Atinux
Copy link
Member

Atinux commented Jul 6, 2018

We will work on it, after long thoughts I don’t think layouts was a great idea but instead rely on a App.vue

@ribrewguy
Copy link

Any update on this? I've found the lack of slots really hard to work around. I often need to change the contents of a default toolbar in the layout depending on certain pages' actions needs. I've been bending over backwards to try to handle this. Vue slots were so easy to use and would be great to have again.

@xxRockOnxx
Copy link

I need this one too. Aside from what @Atinux suggested, is it possible to programatically or suggested to programatically inject a component to layout's component?

Same use case as the others which is modifying a toolbar's contents.

@xxRockOnxx
Copy link

I'm not sure if this is possible, but what if nuxt kind of do something like this behind the scene?

<template>
    <default-layout>
        // actual contents of your page/*.vue
    </default-layout>
</template>

so that the slots in the layout is accessible within page components?

@dylanmcgowan
Copy link

To complete the trifecta of cartoon network avatars +1 for layout slots!

@geocine
Copy link

geocine commented Dec 2, 2018

I hope this issue could be reopened

@lock
Copy link

lock bot commented Jan 1, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Jan 1, 2019
@nuxt nuxt unlocked this conversation Apr 20, 2019
@sobolevn
Copy link

sobolevn commented May 5, 2019

Very sad that this is not supported.

@nelsonlarocca
Copy link

nelsonlarocca commented Jul 10, 2019

Hi guys !

Any update about this ?
I would like to add an extension toolbar containing some icons, each one linked to a different function defined anywhere depending on each page's content
Top toolbar on default layout, extension defined on each page.

Graphically it would be seen as:

FIXED (app) Toolbar having common links to all pages
Extension holding some icons

both "app", I mean, no-scrollable, fixed on top

Any other way to implement that ? I'm trying to get off that idea but seems not to be easy

Thanks !

@cain
Copy link

cain commented Jul 17, 2019

Would love to see this!

@ngunyimacharia
Copy link

Any update on this? Would love to see it implemented!

@connecteev
Copy link

+1 can we get this feature, please? +1 for layout slots. I hope someone is reading this, otherwise I'll open a new ticket and reference this.

PS. Not sure if Nuxt has changed significantly from 2017 when this comment was made:
#1079

@iliyaZelenko
Copy link
Sponsor

Portal-vue helps me.

layouts/default.vue

<template>
  <div>
    My header

    <PortalTarget name="under-header" />

    <nuxt />
  </div>
</template>

pages/index.vue

<template>
  <div>
    <Portal to="under-header">
      My under header
    </Portal>

    My body
  </div>
</template>

It works for me.

@douira
Copy link

douira commented Aug 18, 2019

That seems like a possibility but not a very nice one structurally... But for small changes, it's just fine. You might not want to use too many of those portals though, it might get confusing otherwise.
My solution is to use a base layout that I extend with other layouts. Then I can specify a different layout when I need it to be slightly different. This approach doesn't work if you need to tightly integrate the slot content with the rest of the page though. (and you can't or don't want to use vuex)

@dhritzkiv
Copy link

dhritzkiv commented Oct 7, 2019

portal-vue looks promising, but the lack of SSR support is a non-starter for me.

FWIW, it appears that Vue.js v3 will have portals as a first-class feature: https://github.com/vuejs/vue-next/blob/62a1bcbab0ebea513bb417d9f1485e64b36a6f5a/README.md

@connecteev
Copy link

+1 for slots in layout files so we can get SSR support

@Atinux Atinux reopened this Nov 3, 2019
@douira
Copy link

douira commented Dec 4, 2019

@ the stale bot, this is a feature request so there isn't much to say about that.

@stale stale bot removed the stale label Dec 4, 2019
@stale
Copy link

stale bot commented Jan 3, 2020

Thanks for your contribution to Nuxt.js!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you would like this issue to remain open:

  1. Verify that you can still reproduce the issue in the latest version of nuxt-edge
  2. Comment the steps to reproduce it

Issues that are labeled as pending will not be automatically marked as stale.

@stale stale bot added the stale label Jan 3, 2020
@connecteev
Copy link

connecteev commented Jan 3, 2020

@ stale bot: please keep this open...pretty please?

@xfyre
Copy link

xfyre commented Jun 3, 2020

Would love to have this feature and have layouts in SSR directly supported.

@manutheblacker
Copy link

How can i achieve this ?

@chadwtaylor
Copy link

+1

@prikr
Copy link

prikr commented Aug 29, 2020

+100!

@pmanikas
Copy link

Would be really helpful.

@BeWe11
Copy link

BeWe11 commented Nov 4, 2020

Portal-vue worked for me to inject nav drawer content per page, though I don't need SSR for this content. Would be nice to have support for slots in layouts without this hack... +1

@rifton007
Copy link

+1

Copy link
Member

Atinux commented Nov 26, 2020

Like I said, the actual layouts cannot support easily since we directly use vue-router.

We plan to support this with Nuxt 3 with the <Portal> component.

@rifton007
Copy link

rifton007 commented Nov 30, 2020

Thanks, but in my case I have preferred to not use an additional package.
Finally, I use component like a layout, here a example :

components/grid/default.vue

<template>
  <nav>
    <slot name="nav"/>
  </nav>
  <main>
     <slot/> //default slot
  </main>
  <footer>
    <slot name="footer"/>
  </footer>
  
</template>

pages/index.vue

<template>
  <GridDefault> // component
    <div slot="nav">...</div>
    <h1>Some page</h1>
    <p>Some paragraph</p>
    <div slot="footer">...</div>
  </GridDefault>
</template>

@ghost
Copy link

ghost commented Jul 19, 2021

Yeah using a component as a root element doesn't behave as expected.

I've tried this as in the first example from way back, creating a page component and then using that is a wrapping root element.

The wrapping root component doesn't get access to root instance data props, or even vuex states.

I have a page.props data property set on my root instance, when I look at it in vue dev tools, it's completely populated with data, but yet the when I try to access it page.props.user in the template it throws an error.

I also have this same data stored in vuex state, but when attempting to access it I get null.

import { mapGetters } from 'vuex'

export default {
    mounted() {
        console.log(this.pageProps) /// logs out null
    },
    computed: {
        ...mapGetters({
            pageProps: 'base/page'
        }),
    }
} 

I suppose it might suffice if you only want to put slots in it, but it won't render any data.

Layouts need to render slots, just like Vue does.

@mrleblanc101
Copy link

mrleblanc101 commented Oct 27, 2021

This is now possible in Nuxt 3, this can probably be closed.
I've came here to see if there was a way in Nuxt 2.
Seems like portal-vue is the best approach for my use case.

I have to add a back button in my app-header which is in a layout.
The back button is related to the page and not the layout as it direct the user to the parent page and not a simple $router.go(-1)

@Atinux Atinux closed this as completed Oct 27, 2021
@dawadam
Copy link

dawadam commented Jan 10, 2023

@mrleblanc101 how is this possible in Nuxt 3 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests