Giesburts
Giesburts

Reputation: 7628

Check if a value is supplied to a prop in Vue.js

I am working on a component where I would like to show a badge based on a data property. To supply the data to the component I use a prop. This prop is called status and if present it will be 0 or 1.

Now I would like to check if the value is presented and if so, I would like to render some html in the component. What is the best way to do this? If the data/value is not supplied I would like to not render the html.

HTML

<span>
    <div class="circle-small" :class="{ 'validated': tab.status }"></div>
</span>

So I would like to render this html only if the data to the prop 'status' is supplied. I've tried to use v-if="tab.status" but by doing this the html will not be rendered when the value of status is 0.

Using the required property on the prop like this

status: {
    Type: Boolean,
    required: true,
},

Will also not work, because it is actually not required to use this prop.

Prop

status: {
    Type: Boolean,
},

Somebody with a good solution?

Upvotes: 5

Views: 9857

Answers (2)

Alexander Nenashev
Alexander Nenashev

Reputation: 22734

The solution provided by Julian Paolo Dayag is limited since it handles a boolean prop in this particular case. Using null isn't generic since null is a valid prop value for example for object props. So if we provide null as a prop the solution fails:

Vue SFC Playground

Luckily we have an official Vue way to handle the situation in 2023: https://vuejs.org/guide/components/props.html#prop-validation

 // Object with a default value
 propE: {
   type: Object,
   // Object or array defaults must be returned from
   // a factory function. The function receives the raw
   // props received by the component as the argument.
   default(rawProps) {
     return { message: 'hello' }
   }
 },

So we can provide a function for the default value which will be called if the prop isn't provided. Unfortunately we cannot use local variables in this function because it will be placed outside the component by the defineProps macro. Otherwise we get this compile error:

Error: [@vue/compiler-sfc] defineProps() in <script setup> cannot reference locally declared variables because it will be hoisted outside of the setup() function. If your component options require initialization in the module scope, use a separate normal to export the options instead.

To overcome this I've quickly create some external class to hold components. In our case we store the components under a global symbol WITH_DEFAULTS.

utils.js:

import { getCurrentInstance, onUnmounted } from "vue";

const componentRegisters = {};

export function componentRegister(name){
  return componentRegisters[name] ??= new ComponentRegister;
}

class ComponentRegister{
  #set =  new Set;
  register(comp = getCurrentInstance()){
    this.#set.add(comp);
    onUnmounted(() => this.unregister(comp));
  }
  unregister(comp = getCurrentInstance()){
    this.#set.delete(comp);
  }
  isRegistered(comp = getCurrentInstance()){
    return this.#set.has(comp);
  }
}

Comp.vue:

<script>

import { componentRegister } from './utils';
const register = componentRegister(Symbol.for('WITH_DEFAULTS'));

</script>

<script setup>

const props = defineProps({
  prop: {type: Boolean, default(){
    register.register();
  }},
});

</script>

<template>
  <div>
    The prop is provided: {{!register.isRegistered()}}
  </div>
</template>

And the final solution: Vue SFC Playground

Upvotes: -1

Julian Paolo Dayag
Julian Paolo Dayag

Reputation: 3719

Set the default to null:

status: {
    Type: Boolean,
    default: null
},

then you can check if it was passed like this:

status !== null

This means that the prop status was passed.

Upvotes: 14

Related Questions