Subscribe on changes!

Allow to show the attributes in the rendered html even if are already defined in the component props

avatar
Dec 30th 2021

What problem does this feature solve?

Currently, when you define a component prop and also you define the same as attribute, the html atribute is removed from the rendered html. Ok, is fine, for security, and other several reasons. But this causes an unwanted limitation: you can't play with css attributes selectors, which is a very interesting design pattern when defining (for example) a design system components. For example, is very used in Spectrum Web Components (from Adobe).

https://opensource.adobe.com/spectrum-web-components/components/divider/

<divider :size="size"></divider>

// in divider.vue

 template : '<div :class="$style.root"></div>
 props : {        
        size  : {
            type : String,
            required : true,
            default : 's',
            validator(value){
                return ['s','m','l'].includes(value.toLowerCase())
            }
        }
}
<style lang="scss" scoped module>
.root {
    width: 100%;
    display:inline-block;
}
.root[size="s"]{        
    width:25px; 
    height:25px; 
}
.root[size="m"]{        
    width:35px; 
    height:35px; 
}
.root[size="l"]{        
    width:45px; 
    height:45px; 
}
</style>

This is the result, the attribute "size" is missing and the css selector doesnt work.

<div></div>

If you remove "size" from the component props, it appears again, but you have lost the good parts of vue: validation, self-documentation, reactivity, etc.

<div size="l"></div>

Why choose one option over the other if both are compatible? It would be very useful if the developer could choose whether or not to hide the attribute.

What does the proposed API look like?

I propose to add a new prop option: "visible" (boolean)

 props : {        
        size  : {
            type : String,
            required : true,
            default : 's',
            validator(value){
                return ['s','m','l'].includes(value.toLowerCase())
            },
            visible : true  // by default false
        }
}
avatar
Dec 30th 2021

This is kind of an exotic use case that can be entirely solved in user land:

<div v-bind="$props">

if you need to filter for those you want visible (i.e. you only want props with primitive values):

const visibleProps = computed(() => _.pick(props, ['size']))
< div v-bind="visibleProps">

Just one of a couple of ways.

avatar
Dec 31st 2021

Closing as this is a question and Thorsten provided you with the solution. Remember to use the forum or the Discord chat to ask questions!