Prevent the default action in VueJS when triggering a custom event

One of the challenges I'm facing is with a custom <btn> component that has a specific template structure:

<button @click="$emit('trigger')">
</button>

This component is typically used in forms like so:

<btn>Submit</btn>

However, there are scenarios where I need to include two buttons within the same form. One button should submit the form, while the other should not. The issue arises because both buttons are located inside the form tag, causing them both to trigger form submission. So how can I achieve the desired behavior with Vue?

<btn>Submit</btn> <!-- This button should submit the form -->
<btn @trigger="nextQuiz">Next</btn> <!-- This button should only execute the nextQuiz method -->

Is there a way in Vue to prevent form submission when specifically clicking on the second <btn> element?

Answer №1

To prevent the default behavior of the native click event, you can use the inline option @click.native.prevent:

Vue.component('button', {
  template:`
    <button @click="$emit('trigger')">
      <slot/>
    </button>
  `
})

new Vue({
  el: '#app',
  methods: {
    goToNext() {
      console.log('goToNext')
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js"></script>
<div id="app">
  <form action="">
    <input name="foo">
    <button>Submit</btn>
    <button @click.native.prevent @trigger="goToNext">Go to Next Page</button> 
  </form>
</div>

Answer №2

Define the type attribute.

Vue.component("btn",{
  props:{
    submit: Boolean
  },
  computed:{
    type() { return this.submit ? 'submit' : 'button' }
  },
  template: `
    <button :type="type"  @click="$emit('trigger')"><slot></slot></button>
  `
})

Implementation example:

<form action="">
  <btn submit>Submit</btn>
  <btn>Don't Submit</btn>
</form>

Check out this demonstration.

console.clear()

Vue.component("btn",{
  props:{
    submit: Boolean
  },
  computed:{
    type() { return this.submit ? 'submit' : 'button' }
  },
  template: `
    <button :type="type"  @click="$emit('trigger')"><slot></slot></button>
  `
})

new Vue({
  el: "#app"
})
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e6909383a6d4c8d2c8d4">[email protected]</a>"></script>
<div id="app">
  <form action="">
    <btn submit>Submit</btn>
    <btn>Don't Submit</btn>
  </form>
</div>

@thanksd suggested an alternative approach using the prevent modifier for handling button clicks.

Vue.component("btn",{
  props:{
    submit: Boolean
  },
  template: `
    <button v-if="submit" @click="$emit('trigger')"><slot></slot></button>
    <button v-else="submit" @click.prevent="$emit('trigger')"><slot></slot></button>
  `
})

Answer №3

While other responses offer different approaches such as avoiding the need to prevent the default action, this answer focuses on how to stop the default action using a custom event...

To achieve this, you can transfer the native click event to your custom event by utilizing the $event variable:

<button @click="$emit('trigger', $event)">

Subsequently, in your custom nextQuiz method, you can handle that event and utilize preventDefault to halt the default behavior:

<btn @trigger="nextQuiz">Next</btn>

...

nextQuiz(e) {
    e.preventDefault();
}

Answer №4

If the root element in your case is a button, you have the option to specify the type as button, which will then be applied to the button element itself. The HTML code

<button type="button">Click</button>
by default does not trigger form submission. Therefore, using
<btn type="button">Click</btn>
should prevent the form from being submitted and help simplify your Vue code.

<btn>Submit</btn> <!-- This button is intended to submit the form -->
<btn type="button" @trigger="nextQuiz">Next</btn> <!-- This button is meant to only execute the nextQuiz method -->

To learn more about button types, refer to MDN on button type and the HTML Spec for buttons.

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

Mastering form validation with vuejs: A step-by-step guide

Can anyone provide guidance on implementing form validation in a dynamic form using vue js? ...

An abundance of AJAX requests inundating the server

While working on a straightforward AJAX request, I encountered an issue where the server is sending back 3 responses instead of just one (you can see the example in the attached image). Could someone provide insight into why this might be happening? var ...

An error occurs in the console stating 'Maximum call stack size exceeded' when trying to add data to the database using JavaScript

I've been struggling with a JavaScript error for the past few days and despite scouring through numerous answers on StackOverFlow, none seem to address my specific issue. My goal is to simply submit a record to the database using a combination of Jav ...

Getting started with Sprite Size in Three.js

Could someone assist me in comprehending how three.js initially determines the size/scale of a sprite? Presently, I am dealing with 4 sprites (PNGs with transparency measuring 3000px × 1830px) positioned in 3D space, but I find myself having to enlar ...

Tips for sending repeated ajax requests for multiple forms within a step-by-step wizard

I am currently using a plugin to develop a wizard with steps. I have encountered an issue where the ajax call is being triggered on every step transition, leading to infinite calls. To address this problem, I implemented a check to prevent multiple ajax ca ...

ReactJS attempting to invoke a class function using a dynamically generated button

When attempting to access the deletePost(index) method from the ShowPost class using a dynamically rendered button within the render() step in React, I encounter an issue. The button labeled "click me" successfully retrieves and prints the first item in my ...

The Material UI button shifts to a different row

I need help adjusting the spacing between text and a button on my webpage. Currently, they are too close to each other with no space in between. How can I add some space without causing the button to move to the next line? const useStyles = makeStyles((the ...

Reference loss occurs in Angular Ionic when using @ViewChild

This situation is straightforward I am dealing with a reference in this format @ViewChild('myElement') myElementVar : SomeClass; The element I am referencing appears like this <element #myElement *ngIf="someBoolean"></element> As ...

Is it necessary for me to replicate this function? - jQuery

I have developed a function that creates a transparent information overlay on a current div for a mobile web app. Context: I am using jQTouch, which means I have separate divs instead of loading individual pages anew. $(document).ready(function() { ...

Choosing options from an API response in a REACT-JS application

I have a Select Component in my application and I want it to automatically show the selected data once the response is received. import Select from "react-select"; <Select menuPlacement="auto" menuPosition="fixed" ...

All the details from this run are available in the npm run dev log on Ubuntu

Good day! I've been working on deploying a page built in vue.js, and after uploading all the files successfully, I encountered an issue when trying to run "npm run dev." No matter what I try, including re-installing npm dependencies and starting from ...

Adding 3D primitives to a CSS3DRenderer scene using Three.js: A step-by-step guide

Check out this code snippet: "use strict"; var OrbitControls = THREE.OrbitControls, CSS3DRenderer = THREE.CSS3DRenderer, CSS3DObject = THREE.CSS3DObject, Scene = THREE.Scene, PerspectiveCamera = THREE.PerspectiveCamera, Mesh = THREE.Mesh, ...

Creating a new component in Qt using an already imported type

When trying to create a component of an imported type, such as MyObject, the workaround is currently to create a separate MyObjectComponent.qml file within the application. This process is important for creating components from types found in installed QML ...

Trigger a Vue.js action once an element is generated using v-if

One of the challenges I am facing is loading an element based on a condition (v-if). <div id="food-content" v-if="activeFood" v-cloak> To load it, I use this line of code: app7.activeFood = food; After the element is instantiated, I aim to apply ...

What is the best way to determine the width of a div within a window that has been rendered using React?

I'm working on a task where I need to determine the size of a div (with CSS width set to 100%) and adjust the zoom factor of a component based on this size. The challenge arises during the initial run of the application when the div has not yet been c ...

Implementing dynamic pricing based on quantity in a React Native application

I am trying to implement a feature where the price of a product changes when the user selects a different weight option. For instance, if the user wants to buy mangoes, by default I display the price per kilogram. However, if the user switches the weight f ...

Comparison between WAMP and Live server integration with Facebook for connecting applications

I've been facing some challenges while integrating my website with Facebook Connect. I have been following the instructions provided in this guide. When attempting to run the following code from localhost, please note that for security reasons, my ap ...

Checking the strength of passwords containing special characters

I'm looking to enhance my password validation by including special characters. However, I'm running into an issue where using '%' is causing problems. How can I properly implement validation for special characters? $.validator.addMetho ...

What is the best way to pass my request data to my $scope variable?

I'm currently facing a challenge with this particular topic. My goal is to add the response data that I retrieve from Express to my angular $scope and then direct the user to their profile page. This is how my Controller Function is structured: $sc ...

The dropdown feature fails to function properly when contained within a Bootstrap Popover

Utilizing jQuery v1.12.4, Bootstrap v3.3.7 and Bootstrap-Select v1.10.0. In a popover, I have 2 components. When the popover is opened, I am able to interact with the dropdowns but the selection does not change when clicking an option. You can view the e ...