Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a way to define different name for prop attribute #7943

Open
davletovalmir opened this issue Apr 1, 2018 · 17 comments
Open

Provide a way to define different name for prop attribute #7943

davletovalmir opened this issue Apr 1, 2018 · 17 comments

Comments

@davletovalmir
Copy link

davletovalmir commented Apr 1, 2018

What problem does this feature solve?

In most of cases, it's not really comfortable to use initialProp as prop name, for example, or have normalizedProp inside a component, which takes some passed prop and transforms it. Code looks bloated and reminds more workaround than a good solution.

Having ability to change attribute name of prop would be great. Something like:

rawProp: { attributeName: "prop" }

What does the proposed API look like?

<component size="md"> ... </component>
computed: {
  size: {
    switch (this.rawSize) { ... } // returns something in case blocks
  }
},
props: {
  rawSize: {
    attributeName: "size",
    type: String
  }
}

Thus, using any of proposed solutions above, this.size inside component would return transformed value (for example, h4 or just 4).

I believe having this feature would be very awesome and help us to write cleaner code.

@hatashiro
Copy link
Contributor

hatashiro commented Apr 19, 2018

I'm interested in this feature too. Is this feature confirmed to be implemented? I'm willing to work on this.

Edit:

I'm currently now working on this, please feel free to jump in.

@panhaoyu
Copy link

panhaoyu commented Apr 21, 2018

Besides, there's also another enhancement about props.

Here's a simple code.

props:{
  size: {
    type: Number,
  }
}

And here's a parent component:

<parent>
  <child size="1"></child>
</parent>

We know it's a wrong usage, but I think, now that we provided the field type, we can call Number(value) to change it's type?

After seeing this issue, I think maybe my choice can be a default function of his transform function.

@posva
Copy link
Member

posva commented Apr 21, 2018

Regarding the transform, it's basically coerce from Vue 1 and it was removed. The feature request is about having different name locally for a prop but the transform feature has been asked many times already (#2218, #7657) and it's achievable in userland: https://github.com/posva/vue-coerce-props.

@davletovalmir
Copy link
Author

@posva, I've updated FR description.

@codebryo
Copy link

To give this some life again, I am also very much interested regarding this feature. I would though call it propName to stay in line with it being props:

props: {
  rawSize: {
    propName: 'size',
    type: Number,
    default: 1,
  }
}

@fjc0k
Copy link
Contributor

fjc0k commented Jun 15, 2018

Here is a Vue mixin (fjc0k/vue-messenger) including a series of useful enhancements to Vue components props:

Hope this helps.

@jbieliauskas
Copy link

It's been a while, but I'm going to bring it up again, what's the status of this feature request? Is it confirmed or already implemented?

The proposed (fjc0k/vue-messenger) does not solve the issue. Again, we simply want an alias to prop names, so we wouldn't have to write initialThis, initialThat all the time.

I'm willing to work on this feature, is it confirmed/implemented?

@pdcmoreira

This comment has been minimized.

@posva

This comment has been minimized.

@hrobertson
Copy link

hrobertson commented Jan 18, 2019

It seems to me that this would be preferable:

props: {
  size: {
    type: String,
    alias: "rawSize"
  }
}

Rather than this:

props: {
  rawSize: {
    type: String,
    propName: "size"
  }
}

The external facing prop name should remain as the key in the props object regardless of whether an alias is set or not. Adding an alias for internal use should simply require the addition of a property to that prop spec, not changing the property key.

Here is an example of an existing size prop which the develop later wants to alias within this component:

Original proposal:

props: {
  size: {
    type: String
  }
}

gets changed to:

props: {
  rawSize: {
    type: String,
    propName: "size"
  }
}

My suggestion:

props: {
  size: {
    type: String
  }
}

gets added to:

props: {
  size: {
    type: String,
    alias: "rawSize"
  }
}

@KorHsien
Copy link

KorHsien commented Apr 19, 2020

Edit: Oops, I made a mistake, I was intending to reply to vuejs/rfcs#10. But it's still valid here. I'll reply in there too.

I think the examples list in the Motivation section of the RFC (as well as some use cases commented) are not good arguments for this proposal.

  1. This example expresses its intent quite accurately, the prop name indicates that it's the initial value, which is different from the internal mutable value. I think making this distinction is preferable.
props: ['initialCounter'],
data() {
  return {
    counter: this.initialCounter
  }
}
  1. This example is a bit representative for a lot of arguments around the previously commented use cases of props coercion, sanitization or preprocessing in general.
props: ['size'],
computed: {
  normalizedSize() {
    return this.size.trim().toLowerCase()
  }
}

With the introduction of Composition API, those use cases could be handled elegantly:

props: ['size'],
setup(props) {
  const size = computed(() => {
    return props.size.trim().toLowerCase()
  })

  return {
    size
  }
}

That being said, I'm not entirely against this. The Swift example in the RFC regarding argument labels is what in the similar vein with this proposal.
Take that example into the context of Vue:

props: {
  person: String,
  from: {
    as: 'hometown',
    type: String
  }
}

And take the example of the new <teleport> component (though it's not implemented with normal component options). Its target prop name is to, but it's not ideal to refer it internally as to.
For the sole purpose of renaming (or aliasing), we could do it in setup function:

props: {
  to: {
    type: [String, Element]
  }
},
setup(props) {
  const target = toRef(props, 'to')

  // setting up

  return {
    target
  }
}

But it's not as expressive and cohesive as following IMO:

props: {
  to: {
    as: 'target',
    type: [String, Element]
  }
},
setup(props) {
  // setting up

  return {
    //
  }
}

So, in summary:

  1. IMHO it's a bit of a detour to use this feature to solve the problems of props preprocessing of sort.
  2. This proposal can be useful for providing the feature of argument labels.

@amerikan
Copy link

amerikan commented May 23, 2020

This is a cool feature. I think the idea is similar to that of how Swift allows you to have an internal variable and external parameter name. (https://useyourloaf.com/blog/swift-named-parameters/)

Sometimes it makes sense to have verbose external names for clarity, and shorter names inside the component.

For example, a component can have a long name like this:

<MyTable v-bind:userDataFromSomeAPI="data" />

but inside the component I don't want to refer to it as userDataFromSomeAPI, but just as user.

So I would really like this! I think as or alias are good, though I like as for brevity.

@AndrewBogdanovTSS
Copy link

AndrewBogdanovTSS commented Jun 3, 2020

Another use case for such alias is having components created with :is="component" where you create completely different components with different internal logic, but you pass data inside of such components with a unified prop, something like payload, but for clarity reasons you want the prop to be named differently in every component that receives it

@declantsien
Copy link

Something like from from provide/inject would be awesome also
https://vuejs.org/v2/api/#provide-inject

inject: {
    foo: {
      from: 'bar',
      default: 'foo'
    }
}

@bomzj

This comment has been minimized.

@mleathem
Copy link

mleathem commented Jul 23, 2021

Any progress? would be a nice to have...!
(my use case is to support international developers, so the prop name is more intuitive in each language)

as a workaround: (in the meantime) add a new prop for every alias, and then using computed value ... but it adds more lines to the component (compared to a simple one line as @hrobertson suggested with:
props: { size: { type: String, alias: "rawSize" } }

@kalnode
Copy link

kalnode commented Jan 10, 2024

Another use case for such alias is having components created with :is="component" where you create completely different components with different internal logic, but you pass data inside of such components with a unified prop, something like payload, but for clarity reasons you want the prop to be named differently in every component that receives it

This is my use case. Currently what I do isn't terrible, just looking for more elegance and eliminating one extra variable:

<component :is="component" :payload="data" />

With 20 components or so, and inside any given component pass prop payload into a const.

Example: Customer component:

const props = defineProps<{
    payload: any
}>()
const Customer = computed(() => props.payload)

Which allows me to use Customer in the template, and not payload peppered everywhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests