Passing non-prop attributes to component sub-elements

I’m building a small UI component library, the template for each will be something like the following:

<div class="ui field">
        <!-- component internals -->

I know from the docs that non-prop attributes (i.e. class, style, etc) will be appended into the root element:

Resulting in something like this:

<div class="ui field foo bar" style="foo: bar">

Is there a way to pass non-prop attributes to any child elements, for example, passing some additional constraints to a child <input> element, for example?

<div class="ui field">
        <input foo="1" bar="2" baz="3">

The only thing I can think is to have a prop called attributes into which a string of attributes can be passed, and these are set in mounted().

Not very “Vue” but it should work.

Yes, it’s a brand new feature! :smiley:

Ah, great!

How are child attributes defined on the component markup?

I was having my own think about precisely this, and thought something like this would be nice:


      <label ref="label">
      <input ref="input">

Component declaration:



<div class="foo">
   <label class="bar">
   <input class="baz">

It took me a minute to understand that.

You would have to do that yourself. All Vue gives you is this.$attrs, which is an object with all the attributes that were not matched to props.

  'input.class': 'bar'

But it should be quite trivial to write a function that reads the keys and splits by ., using the first section as a ref.

1 Like

That’s actually pretty sweet that it’s that flexible.

But it should be quite trivial to write a function that reads the keys and splits by ., using the first section as a ref.

And, yes :slight_smile: Here it is:

function getAttrs(attrs, name, delim = '.') {
    const prefix = name + delim
    return Object
        .filter(key => key.indexOf(prefix) === 0)
        .reduce(function (output, key) {
            output[key.replace(prefix, '')] = attrs[key]
            return output
        }, {})

var $attrs = {
    '': 1,
    '': 2,
    'label.baz': 3,

getAttrs($attrs, 'input')

How does one attach the attributes? Using the spread operator as you outlined in your comment?

<dropdown v-bind="{ ...$props, $attributes.type }"/>

Where? To the component (in the parent) or to the input in your component, as per your example?

To elements within the component, in my example, the input

I your example, like this:

<input v-bind="getAttrs($attrs)"

no need to use the rest spread unless you also want to add other dnymaic attributes inline

Ok, so just simply v-bind.

Now the release note example is clear, along with the listeners:

  <input v-bind="$attrs" v-on="$listeners">

Thanks! This is great :slight_smile:

Look like it might be time to review the core docs.

v-bind has all this info in it:

v-bind="$attrs" v-on="$listeners" solves the problem for most things passed into the component, but what about forwarding refs (e.g In my case I’ve wrapped a 3rd party component and want to pass the attrs, listeners AND ref (AKA everything) through to the wrapped component.