material-components-vue
material-components-vue copied to clipboard
v-ripple on router-link: mdc classes get lost
Describe the bug
When adding v-ripple to router-link, the ripple only works once, because the mdc- classes vanish on route-change
Desktop:
- OS: Mac
- Browser Current Firefox & Chrome
Possible fix I fixed this by using a MutationObserver and re-adding the previous classes.
interface MDCRippledElement extends HTMLElement {
mdcRipple: MDCRipple
}
const mutationConfig: MutationObserverInit = {
attributeFilter: ['class'],
attributes: true,
attributeOldValue: true,
}
const observer = new MutationObserver(mutationCallback)
function mdcClasses(className: string | null) {
return className ? className.match(/mdc-[a-z-]+/g) || [] : []
}
function mutationCallback(mutationList: MutationRecord[]) {
mutationList.forEach(({ target: el, oldValue }) => {
const target = el as MDCRippledElement
// re-add the lost mdc-classes
const currentMDCClasses = mdcClasses(target.className)
if (!currentMDCClasses.length) {
const oldMDCClasses = mdcClasses(oldValue)
target.classList.add(...oldMDCClasses)
}
})
}
...
bind() {
observer.observe(el, mutationConfig)
}
(this will not work, if the customized modifier is used))
@meibegger Before I find the cause, you can use the scope slot in <router-link>.
<router-link
to="/about"
v-slot="{ href, route, navigate, isActive }"
>
<a v-ripple :active="isActive" :href="href" @click="navigate">{{ route.fullPath }}</a>
</router-link>
This might be easier than using the MutationObserver.
Thank you!
But as soon as you toggle the class on the link, you get the same problem:
<a v-ripple :class="{active: isActive}" :href="href" @click="navigate">{{ route.fullPath }}</a>
So the workaround would be this https://router.vuejs.org/api/#v-slot-api-3-1-0