fedorqui
fedorqui

Reputation: 289765

Can I pass optional props to a component in Vuejs so they are passed to a component?

I have some recurring calls to a component from different views, such as:

<highcharts
    :options="getSomeData"
    :constructor-type="'mapChart'"
    :callback="getSomeDataCallback"
    class="someFancyStyle"                                                        
/>

Since it is within a more general block that loads data and controls the errors, I have created a new component "GraphDisplay" to handle this:

<template>
    <div>
        <div v-if="loading"> loading... </div>
        <div v-else-if="error"> error... </div>

        <div v-else>
            <div v-if="highcharts">
                <highcharts
                        :options="data"
                />
            </div>
            <div v-else>
                <slot></slot>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    name: "GraphDisplay",
    props: {
        loading: Object,
        error: Object,
        data: Object,
        highcharts: Boolean,
    },
};
</script>

So now I have to just call GraphDisplay with:

<GraphDisplay
        :loading="bla.isLoading"
        :error="bla.errors"
        :data="bla.data"
        highcharts
/>

or

<GraphDisplay
        :loading="bla.isLoading"
        :error="bla.errors"
>
     <another graph>
</GraphDisplay>

This works well.

The thing now is that <highcharts> sometimes has more than one prop, as seen in the first code I posted here: it may have "constructor-type", "callback", "class", or others.

Is there a way to pass props that are optional, so they are used when calling the component? I tried passing a new prop "config" and feed with possible values:

    props: {
        loading: Object,
        error: Object,
        data: Object,
        highcharts: Boolean,
        config: {
            type: Object,
            default: () => {}
        },
    },

So the call is like this:

<GraphDisplay
        :loading="getSomeData.isLoading"
        :error="getSomeData.errors"
        :data="getSomeData.data"
        :config="{
                    constructorType: 'mapChart',
                    class: 'someFancyStyle'
                }"
/>

And the component uses it as follows:

<highcharts
    :options="data"
    :constructor-type="config.constructorType"
    :class="config.class"
>

However, things seem to be overly complicated and I don't know if this is the path to follow. All I would like is to have a set of props marked as optional that get delivered to <highcharts> in case they are provided. I think in the Spread syntax { ... } so I could say:

<div v-if="highcharts">
    <highcharts
            :options="data"
            ...config // adding extra data here
    />
</div>

Upvotes: 3

Views: 6580

Answers (1)

tony19
tony19

Reputation: 138316

The semantics in your example, where multiple props from an object are bound at once, indeed exists in Vue with the v-bind (without an argument) directive.

In this case, v-bind="config" binds all properties from config to the component. Non-applicable props from config would be bound as HTML attributes (visible upon inspecting the element from DevTools), or as properties otherwise. If config is empty, no bindings would occur.

Assuming the config value below:

const config = {
  nonExistentProp: 'foo',
  constructorType: 'mapChart',
  class: 'someFancyStyle',
}

The following template:

<highcharts v-bind="config" />

would be equivalent to:

<highcharts nonexistentprop="foo" class="someFancyStyle" constructor-type="mapChart" />

demo

Upvotes: 4

Related Questions