Nuxt.js: Change default layout programmatically

Created on 3 Mar 2019  路  12Comments  路  Source: nuxt/nuxt.js

What problem does this feature solve?

Role-based applications could load different layouts based on the user's role. Currently, I am utilizing the layout property in every component like:

  layout(context) {
    return context.store.state.auth.user.role
  } 

my layout folder is structured like:
layout/

  • admin.vue
  • default.vue
  • manager.vue
  • norole.vue
  • user.vue

Which works great until I create a new component and forget to throw this snippet in.

What does the proposed changes look like?

I am wondering if having a global method to set the default layout would be a useful feature. In the scenario of programmatically changing the layout based on a user's role, I would image it would be called like:

this.$layout.setDefault(this.$auth.user.role + '.vue'); // admin role -> admin.vue
// or maybe even bind it?!
this.$layout = this.$auth.user.role + '.vue';

Maybe I am overthinking this. Thanks!

This feature request is available on Nuxt community (#c8764)
feature-request

Most helpful comment

I think that's already possible:

$nuxt.setLayout('admin')

You could just watch the store.state.auth.user.role and change layout.

All 12 comments

I think that's already possible:

$nuxt.setLayout('admin')

You could just watch the store.state.auth.user.role and change layout.

Thank you! Do you know of any way I can access this.$nuxt from within vuex?

@russellsean on client-side: window.$nuxt.

PS: Closing here as the requested feature is already included.

I noticed this only changes for the current component. If you route to another page it changes back to the default layout. Is there any way to change the default layout for the entire app?

Jumping in here, is there a way to use setLayout from inside asyncData?
All I found is accessing context.app.methods.setLayout but it doesn't change the actual layout of the printed page.

@russellsean @altryne did you find the solution?

@marko-mlinarevic negative. I took a different approach. I use the same layout for authenticated users, but load components based on their role.

@russellsean I did a hacky solution.

when landing on page I do this in fetch

          beforeNuxtRender(({ nuxtState }) => {
            nuxtState.layout = store.state.layout;
          })

and when changing pages I do this in created

    this.$nuxt.setLayout(this.$store.state.layout)

It works for now

Hi guys the solution on the client works very well, just need a loading to cover the layout changes, but in the fetch the solution for the backend works but throws some errors on the console about the Virtual DOM, is there another solution to resolve in the serve side? Because I think is a feature that the dev wanted to them.

Maybe my approach can help.
In default.vue layout I placed the layout change in the data().
You can place the layout switching logic in each layout.
data() { if(this.$auth.loggedIn) { this.$nuxt.setLayout('different-layout'); } }

Clunky but works better than $nuxt.setLayout since it works through context and seems to have no delay on the rendering.
context.route.matched[0].components.default.options.layout = "admin"

The proposed $nuxt.setLayout unfortunately does not immediatly work through middleware. It only works inside a timeout with 0 ms delay but then the switch is visible to the user.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jaredreich picture jaredreich  路  3Comments

o-alexandrov picture o-alexandrov  路  3Comments

surmon-china picture surmon-china  路  3Comments

mattdharmon picture mattdharmon  路  3Comments

uptownhr picture uptownhr  路  3Comments