Skip to content

When prop's type is plain object, it's wonderful to merge default object and prop object when they all exist #6556

@ulivz

Description

@ulivz
Member

What problem does this feature solve?

When the parent component passes prop to the child component if the prop type is object, and its value has been given as a plain object, at the same time, and the child component's default value build function also returns a plain object, we should merge the default object and the prop object (shadow merge), which is very conducive to customize the default value. and also greatly enhance the feel of writing Vue components.

A simple example:

//parent component
<Editor :options="editorOption"></Editor>

data () {
      return {
        editorOptions: {
          line: true,
          autoCloseTags: true
          }
        }
      }

// Child component
    props: {
      options: {
        type: Object,
        default () {
          return {
            line: false
            mode: 'text/javascript'
          }
        },
        required: true
      },
    },

In correct version, the options in child component will be rendered as:

{
          line: true,
          autoCloseTags: true
}

but the ideal result should be:

{
            line: false
            autoCloseTags: true
            mode: 'text/javascript'
}

For performance reasons, we just need to do shadow merge.
It will greatly enhance the writing feeling for some flexible and largely configurable component.

What does the proposed API look like?

No need new API, just handle in the logic of check default value

Activity

ulivz

ulivz commented on Sep 10, 2017

@ulivz
MemberAuthor

I tried to realized this feature at: My forked branch
And I also write a UT at the above condition
But several another UTs of props failed. So I think my change is not comprehensive and reliable.

yyx990803

yyx990803 commented on Sep 13, 2017

@yyx990803
Member

Unfortunately this will be a breaking change, so unlikely to happen :/

MatteoGabriele

MatteoGabriele commented on Apr 29, 2018

@MatteoGabriele

why closing a feature request only because causes a breaking change?
aren't breaking changes supposed to go into major versions?

a feature that merges props it's actually super nice and it's something that I have to do manually every time because it's a very common scenario when creating complex components.
I get the breaking change but why not add this feature to a roadmap or something?

@yyx990803 Besides my point on the "closed ticket", could you suggest an elegant and reusable way to achieve this kind of behavior? I could maybe write a plugin :)

Thanks for your time

ksidibe

ksidibe commented on Aug 22, 2018

@ksidibe

@MatteoGabriele and @ulivz , I agree with everyone who says that this should be the behavior. Just because I want to override one attribute/property, I should not mean that I have to provide all the other properties.
Having said that, here's how I've achieved that behaviour;

props: {
            student: {
                type: Object,
                default: function(){
                    return {}
                }
            },
            labels: {
                type: Object,
                default: function(){
                    return {
                    };
                }
            }
            
        },
computed: {
            mergedLabels: function(){
                return Object.assign(
                    {},
                    {
                        billing: 'Billing',
                        firstName: 'First name',
                        generalInfo: 'General Info',
                        middleName: 'Middle name',
                        lastName: 'Last name',
                        dob: 'Date of birth',
                        gender: 'Gender',
                        placeOfBirth: 'Country of birth',
                        nationalities: 'Nationalities',
                        gradeLevel: 'Grade level'
                    },
                    this.labels
                )
            }

In the above case, I want to be able to override the labels.
instead of using labels.firstName, I use mergedLabels.firstName
Important Note: Make sure the in the call to Object.assign(), this.labels is the last argument. Otherwise, the value passed in by the user will be overridden.

CoolGoose

CoolGoose commented on Oct 24, 2018

@CoolGoose

@yyx990803 in the light of Vue.js 3 can we please reconsider this option ?

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @CoolGoose@yyx990803@posva@ksidibe@MatteoGabriele

        Issue actions

          When prop's type is plain object, it's wonderful to merge default object and prop object when they all exist · Issue #6556 · vuejs/vue