Skip to content

Allow props to have different internal and external names #7569

@decademoon

Description

@decademoon

What problem does this feature solve?

Consider the <input> element. It maintains its own internal state for its value (by the browser) irrespective of whether or not it is being driven by v-model.

After looking at some Vue component libraries, most of the components externalize their state through props, meaning that the parent component must define the value for that component in its data and use v-model to wire it up -- the component cannot be used without v-model because it doesn't maintain the state internally to the component.

Ideally I'd like to author input components that satisfy the following requirements:

  • Can be used without v-model (the component maintains the state itself)
  • Can be used with v-model (the state is driven entirely by the prop emitting input events)

This results in somewhat messy code like this:

Vue.component('checkbox', {
  template: '<div class="checkbox" @click="toggle">{{ internalValue ? "Checked" : "Unchecked" }}</div>',
  
  props: {
    value: {
      type: Boolean,
      default: false,
    },
  },
  
  data() {
    return {
      internalValue: false,
    };
  },
  
  watch: {
    value: {
      immediate: true,
      handler(value) {
        this.internalValue = value;
      },
    },
    
    internalValue(internalValue) {
      this.$emit('input', internalValue);
    },
  },
  
  methods: {
    toggle() {
      this.internalValue = !this.internalValue;
    },
  },
});

In order to distinguish between the prop and the data, I've used value and internalValue respectively. The problem is that value is rarely used in the code (it's only used in the watcher) and I have to remember to use internalValue throughout the component's code and template instead of value (since internalValue is the mutable source of truth).

To avoid this, I could instead name the prop externalValue and the data value, but now I would have to use <checkbox :external-value="x"> which is not ideal (the external prop should be called simply "value").

I'm proposing a feature in which you can specify what internal name a prop should be exposed as within the component without changing the external name of that prop in templates (kind of like how method arguments work in objective-c).

What does the proposed API look like?

Vue.component('foo', {
  props: {
    value: {
      internalName: 'valueProp',
    },
  },

  template: '<div>{{ valueProp }}</div>',
});
<foo value="bar">

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions