I couldn't see a way to do this even through my layout file; I want to add a class to the <html> tag that does overflow: hidden !important when a modal is present so that I can prevent scrolling in the background.
I figure since I have modals in different components I would use vuex to globally communicate:
my store/index.js
import Vuex from 'vuex'
const store = () => new Vuex.Store({
state: {
modal: false,
},
mutations: {
modalOn (state) {
state.modal = true
document.getElementsByTagName('html')[0].classList.add('is-clipped')
},
modalOff (state) {
state.modal = false
document.getElementsByTagName('html')[0].classList.remove('is-clipped')
},
},
})
export default store
Then in my component I add a watcher that hits these mutations when the modal is on/off:
watch: {
'modal' (value) {
if (value) {
this.$store.commit('modalOn')
} else {
this.$store.commit('modalOff')
}
},
},
Am I doing it wrong? is there a better approach?
I think you're over complicating it, I'm not sure you really need to use the store for this.
A better approach would probably be a child component that adds the class in its created lifecycle event and removes it on its destroyed lifecycle event. You could probably even house the modal's logic/template within the child component and bind it to a route - that way user could even refresh the page and get back the same modal state (open/closed).
@homerjam well the main point is i want to simplify and globalize this functionality so that all my modals can use this, and i don't really see any other way besides a store.
I don't see a reason to need it w/in routes (yet) but nice suggestion
To add a custom class to your HTML tag, you can use Document.
@alexchopin thanks but I not only need to add a custom class but I need to be able to add/remove this class based on wether or not the modal is on
@acidjazz I needed exactly that too (to fix some wonky iOS scrolling) and this did the trick for me
export default {
head() {
return {
bodyAttrs: {
class: this.modalOpen ? 'm-open' : 'm-close'
},
htmlAttrs: {
class: this.modalOpen ? 'm-open' : 'm-close'
}
}
}
}
On one hand, that's reactive.
On the other hand, it doesn't have all the affordances :class in template has, such as passing {class1: true} or ['class2'], or camelCase.
You can do this in a jiffy though:
export default {
head() {
return {
htmlAttrs: {
class: (Array.isArray(this.classes)
? this.classes
: Object.entries(this.classes).reduce((acc, entry) => {
if (entry[1]) acc.push(entry[0])
return acc
}, [])
)
.join(' ')
.replace(/([a-z])([A-Z])/g, '$1-$2')
.toLowerCase()
}
}
}
}
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.
Most helpful comment
@acidjazz I needed exactly that too (to fix some wonky iOS scrolling) and this did the trick for me