Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I merge HTML attributes with component data in Vue?

I'm trying to extract some repeated code into a Vue component. I want to be able to pass a list of CSS classes into the component using the class HTML attribute, and merge those with a "default class" that is defined in the component. I want the public interface of this component to resemble a standard HTML element, but if I try to use "class" as a prop Vue throws an error about using a JS keyword. If I try to use $attrs, my default class gets wiped out.

Is it possible to merge HTML attributes with local component data, and use the result in my template? Below is what I would like to achieve:

<template>
  <img src="imageUrl" class="classes"
</template>

export default {
  computed: {
    imageUrl() { return 'urlString' },
  },
  classes() { return `${this.$attrs.class} default-class` }
}

And I'd expect an implementer to be able to use my component like so:

<CustomImageComponent class="class-name another-class" />

Which I'd expect to render this:

<img src="urlString" class="class-name another-class default-class" />
like image 824
mchandleraz Avatar asked Oct 31 '25 04:10

mchandleraz


1 Answers

It already happens (automatically)

using <CustomImageComponent class="class-name another-class" />

will render<template><img src="imageUrl" class="my-default-class"/></template>

as <img src="imageUrl" class="my-default-class class-name another-class"/>

(in that order, with the in-template class first, and the passed classes after)

the issue is that if you have a nested DOM element that you want to apply it to, you cannot do that and you will have to use a prop

ie:

using <CustomImageComponent class="class-name another-class" />

will render<template><div><img src="imageUrl" class="my-default-class"/></div></template>

as <div class="class-name another-class"><img src="imageUrl" class="my-default-class"/></div>

and there's nothing you can do about that, other than use custom props.

like image 196
Daniel Avatar answered Nov 02 '25 18:11

Daniel