Reactively add/remove a class name to <body>, from within a component...
I have a component with a boolean ref. As long as
myBool.value === true
, I'd like to bind a class name to <body>
.
I've attempted to use the useMeta
and useMetaSafe
composables (useHead > bodyAttrs.class) but it doesn't change reactively.
Any idea what the heck I'm missing? This is driving me nuts and the documentation makes it sound relatively simple.29 Replies
useHead
works to set the initial value of title
, bodyAttrs.class
, etc -- but none of these properties appear to be reactive.how are u using
useHead
You should use:
useHead({
bodyAttrs: {
class: 'YOUR-CLASS-NAME'
}
})
But indeed, as the doc says (https://nuxt.com/docs/api/composables/use-head), bodyAttrs
is non-reactive...@deetstrab try with a composable for the class
like
useHead({
bodyAttrs: {
class: () => test === true ? 'clas-true' : 'class-false'
}
})
It says it is reactive, though?
This is exactly what I'm doing and have tried all variants of this that I know to.
I need to understand why this needs to be a function to work? What would be a good resource to read to better grasp this concept? Thanks in advance! π
Is there a reason it has to be body and not just a wrapper div in app.vue?
Thank you all for your helpfulness and thoughtful replies
As I see it, yes. I needed to disable scrolling of the website while my mobile nav is open.
It's possible a wrapper div would have worked too - this is a pattern I've used in many mobile navs that I've built over the years, though.
You could just have a global utility class:
and then you can just use a computed property or a watcher to apply/remove
document.body.style.noScroll
as needed?I do something similar for locking the body when a modal is in place:
Yes but isn't targeting the DOM nodes like this an anti-pattern in Vue/Nuxt?
That's exactly how I do it in vanilla/es
I just wanted to force myself to do it the Vue/Nuxt way
it's just adding/removing a class - it's what Vue is doing to the DOM underneath its hood, too.
well of course and I see it as that simple too, fwiw - I've just been taught that it's an antipattern. I didn't consider it for that reason, but you're absolutely right - it's a simple solution that works perfectly!
I need to get a better understanding of why this only works within an anonymous function
Did you try something like:
no, I was (formerly) just using a ternary eval
the "computed" part of that would be necessary
I really appreciate your help and conversation π thank you, my friend
π
if you don't wrap with a function or computed the value gets resolved immediately, meaning you're providing a literal to useHead which it can't bind reactivity to
alternatively you can avoid the function syntax if you provide the ref explicitely like so
this will work the same as the Vue template
I hate to piggy-back on this, but at the same time I am dealing with something very similar. The primary difference being that I don't even have any sort of conditional for the class.
My goal is to have a body class that shows up on some pages and not on others. I thought it would be simple enough if I set
bodyAttrs
differently between pages, but that doesn't seem to be doing it. I have tried both setting the value bodyAttrs: { class: }
to a ref
and adding an anonymous function as above, but the class still seems to stick between pages. Any ideas??
Here's what I have for my pricing page:
And here's another page:
The title and page description changes, so I'm not sure why the bodyAttrs
doesn't.try
Thanks! That didn't seem to work.
At this point, I think it might have something to do with the way I have my page routes set up. For some reason, I have a
software.vue
page set up in the root of my pages
folder in addition to having the nested routes under /software
. I remember reading in the documentation during the early stages of my project about this being an option, but I don't remember why exactly I chose this structure as I think it has caused more headaches than it's worth.this was fixed recently in unhead FYI
GitHub
Body style background image does not update when theme changes Β· Is...
Environment Operating System: Darwin Node Version: v21.6.2 Nuxt Version: 3.11.1 CLI Version: 3.11.1 Nitro Version: 2.9.5 Package Manager: [email protected] Builder: - User Config: devtools, typescript, ...
Wait. You mean to tell me this is a bug and I'm not crazy?? π
I manually updated to the latest version and it still doesn't seem to work... π«
also cleared lock file and all?
then please file a bug report if possible (similar to that one or easier)
your best bet is to make a minimal reproduction in Stackblitz and we can either guide you in the right direction or fix the bug you've ran into
afaik this shouldn't be an unhead bug in the latest
I'm sorry for the ignorance, but what do you mean by this? The package-lock file??
you can do a nuxi upgrade with the force param to HARD UPGRADE π - give that a shot
npx nuxi upgrade -f