How can we pass an optional boolean prop in Vue 3?

Currently, I am in the process of developing an application using Vue 3 and TypeScript 4.4, bundled with Vite 2. Within my project, there exists a file named LoginPage.vue containing the following code:

<script lang="ts" setup>
const props = defineProps<{
  message?: string;
  redirectOnSubmit?: boolean;
  showRegisterLink?: boolean;
}>();

console.log({ ...props });
</script>

<template>
  ... login form and other elements
</template>

This particular component is then passed to vue-router:

export const router = createRouter({
  history: createWebHistory(),
  routes: [
    { name: RouteName.LOGIN, path: "/login", component: LoginPage },
    { name: RouteName.REGISTER, path: "/register", component: RegisterPage },
  ],
});

The issue I am encountering arises when the login page's setup script is executed, as it outputs the following:

{ redirectOnSubmit: false, showRegisterLink: false, message: undefined }

I'm puzzled as to why my optional boolean props are defaulting to false instead of undefined. Is there a way to disable this behavior? Even if I change message to message?: boolean, it still defaults to false.

My intention is to set these props to true by default if no value is provided. However, the current setup does not differentiate between passing false and omitting the props entirely.

Answer №1

Vue automatically assigns a default value of false to Boolean props if no initial value is specified in the prop declaration. The creator of Vue provides an explanation:

The boolean casting behaves similarly to boolean attributes: any value present is considered true, while absence indicates false.

If you wish to set the default value of a prop to true, you can define it with a default option of true using the object-based syntax for prop declarations. Here's an example using the Options API:

<script>
export default {
  props: {
    myOptionalBool: {
      type: Boolean,
      default: true, 👈
    }
  }
}
</script>

Option 1: defineProps(props)

Within <script setup>, defineProps() accepts the prop declaration object illustrated above as a function argument. As defineProps() only allows either the function argument or the generic type argument, all props must be declared within the function argument itself:

<script lang="ts" setup>
const props = defineProps({
  message: String,
  showRegisterLink: {
    type: Boolean,
    default: true,
  },
  redirectOnSubmit: {
    type: Boolean,
    default: true,
  },
})
</script>

Check out demo 1 here

Option 2: withDefaults() and defineProps<T>()

The withDefaults() macro pairs with defineProps<T>() to establish default values for specific props:

<script lang="ts" setup>
interface Props {
  message?: string
  redirectOnSubmit?: boolean
  showRegisterLink?: boolean
}
const props = withDefaults(defineProps<Props>(), {
  redirectOnSubmit: true,
  showRegisterLink: true,
})
</script>

Explore demo 2 here

Answer №2

Answering the question more directly:

In order to properly address this issue, it is necessary to utilize withDefaults and explicitly set undefined as the default value:

const properties = withDefaults(defineProperties<{
  text?: string;
  displayLink?: boolean;
  includeImage?: boolean;
}>(), {
  displayLink: undefined,
  includeImage: undefined
})

By following this approach, the optional boolean attributes will be accurately represented as undefined rather than false when not specified.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for setting up FastAPI to handle server-side rendering for Vue 3?

Is it possible to achieve server-side rendering with FastAPI similar to how it's done with node.js and Vue SSR? Are Jinja2 templates or SPA the only options for rendering dynamic pages? Challenges: Avoiding SPA for better SEO Issues with excessive p ...

Navigating through the key type within a mapped structure

I am working with a mapped type in the following structure: type Mapped = { [Key in string]: Key }; My understanding is that this setup should only allow types where the key matches the value. However, I have found that both of the cases below are permitt ...

Ways to encourage children to adopt a specific trait

Let's discuss a scenario where I have a React functional component like this: const Test = (props: { children: React.ReactElement<{ slot: "content" }> }) => { return <></> } When a child is passed without a sl ...

Task failed: NativeScript encountered an error while attempting to merge dex archives

Encountered an error while developing an NS + Vue application - Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'. > com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives ...

Managing onChange in a ReactJs project

Currently, my React tsx page features input boxes like the following: <textarea value={this.state.myData!.valueOne} onChange={(e) => this.handleValueOneChange(e)}/> <textarea value={this.state.myData!.valueTwo} onChange={(e) => thi ...

A step-by-step guide on testing Pusher integration using Jest unit testing in Vue JS

In my Vue.js project, I am attempting to simulate the behavior of pusher when writing unit tests using JEST. What is considered the most effective method for mocking both pusher and its associated functions? ...

Prevent animations on child elements with Vue.js

I am dealing with a scenario where I want to remove the fade transition on a child div within a <transition> component. The reason for nesting it is to prevent layout flickering, which can be demonstrated in a fiddle if necessary. In the fiddle belo ...

Concealing Vue object properties

Is it feasible to indicate specific object properties that should not be displayed? This can come in handy for debugging purposes, especially when dealing with large objects or objects that create a loop. For instance, let's say we have an object: c ...

Angular 2 lacks compatibility with SVG

I have a website where I want to include SVG images inline with my HTML using Angular 2. However, when I try to load the SVG icons within a component, they do not display correctly. Instead, I see the following: https://i.sstatic.net/Ozo6E.png You can vi ...

Error: Code cannot be executed because the variable "sel" has not been defined in the HTML element

Every time I try to click on the div, I encounter an error message stating 'Uncaught ReferenceError: sel is not defined at HTMLDivElement.onclick' I am currently developing with Angular 8 and this error keeps popping up. I have read through simil ...

Getting content for a component by clicking a button outside the component in Vuejs – here's how!

My challenge is to update the content of a modal whenever a button outside of the component is clicked. The goal is to update an item slug that will be used to fetch content from an API. This task is within Vuejs, and I am still learning how to work with ...

Tips for stopping </p> from breaking the line

<p>Available: </p><p style={{color:'green'}}>{props.active_count}</p><p>Unavailable: </p><p style={{color:'red'}}>{props.inactive_count}</p> I want the output to display as two separate l ...

Utilizing Mapbox-gl within a Vue.js single file component with Quasar-Framework integration

I'm attempting to incorporate a Mapbox-gl-js Map into a single file Vue component within the Quasar Framework, but I'm struggling to make it work. I've come across examples of Googlemaps with Vue and Mapbox with React, and I'm trying to ...

How to dynamically order components in Vue?

Any help you can offer in advance will be greatly appreciated. I am currently working on an application that utilizes Vue's dynamic component tag feature. If you'd like to learn more about dynamic components in Vue, please check out this link. ...

BehaviorSubject Observable continuously notifies unsubscribed Subscription

Utilizing a service called "settings", initial persisted values are read and provided through an observable named "settings$" to components that subscribe to it. Many components rely on this observable to retrieve the initial values and exchange updated va ...

Tips for incorporating moment.js library into an Angular 2 TypeScript application

I attempted to utilize TypeScript bindings in my project: npm install moment --save typings install moment --ambient -- save test.ts file content: import {moment} from 'moment/moment'; I also tried without using TypeScript bindings: npm inst ...

Adding comments in TypeScript: A quick guide

Hey there, I'm new to TS and could use some help. Here is the code snippet I have: I want to comment out the logo but adding "//" and '/*' doesn't seem to work. This is what I tried: // <LogoComponent classes={{container: style.log ...

What is the best way to implement a filter for incoming data within a function?

I am attempting to trigger a function when a button is clicked using Vue. I need to apply a specific filter to the data being passed into the function in order for it to execute correctly. Below is my attempt: <button v-on:click="functionName(variable| ...

"What is the best way to determine the data type of an object retrieved from an API in TypeScript

Hey there, I'm currently developing a web application using Angular 2 and I'm focusing on implementing an exception handling mechanism. To achieve this, I've created a model that mirrors the object structure I will receive from the server (E ...

The Vuex action is unable to execute a mutation

I am currently working on implementing an authentication feature for a website using Firebase. Whenever a user logs into Firebase, my store's action is triggered, which in turn commits a mutation to set the state with the userID. However, I keep encou ...