[Vuejs]-Vue3 CoreUI CMultiSelect submitting unintentionally when 'Select all options' is clicked

0👍

Answer from myself since that’s how coding is sometimes.

1) Temporary Fix

I found how to implement my temporary fix, where I needed to type :select-all="false" with a colon to bind it instead of select-all="false". For newbies like me, : is short for v-bind in Vue, which binds data to components so that when the data changes, the state of the app changes to reflect it.

Several days later…
2) Robust Fix

In order to describe the robust solution to this problem, I will be outlining what I learned about JS events and how Vue handles watching them and their propagation. I will also be covering a bit of how Vue uses what you write to generate HTML code, specifically how the CoreUI multiselect component generates HTML elements like <select> and <options>.

What was causing the error was the fact that the <CMultiSelect> was nested in a parent <CForm>. This in itself is not bad practice, and is even practical given that some forms should have multiple selection fields alongside their other form fields. However, a problem arose when a user clicked the ‘Select all options’ button. This is because putting a <CMultiSelect> into your code instructs Vue to compose a collection of elements at runtime that are abstracted away from you, the developer. Vue generates a <select> block that contains an <option> element for each option that you bind to the <CMultiSelect>. It also generates a ‘Select all options’ <button> that for some reason can produce a SubmitEvent. When this event is produced, it propagates upward since it was not stopped with event.preventDefault() or event.stopPropagation(). It gets caught by the submission watcher of the parent <CForm> and triggered the custom form submission in my project. This behavior was also caused by the small x buttons to delete tags from the multiselect view, but I did not look into the generated code with console.log()s enough to figure out why.

I was able to fix this problem by checking the submitter property of event.

Side note: I would recommend doing a quick console.log(event) in any event handler methods that you are having trouble with, since events are much more complex than I thought and you will be able to see properties that can be of use to you.

event.submitter is a property of submit events, and returns the HTML element that generated that particular submission. In my case, it returned the ‘submit(?)’ button of the <CMultiSelect> which was of the form <button ...>Select all options</button>. I then accessed just the contents with event.submitter.innerHTML (which produced just Select all options) and if it matched this content, do nothing. This could also be used for a form with multiple submission buttons that trigger different types of submission (perhaps alternate processing of user data), because it allows you to tell where the event is coming from.

For example, the below form…
<form @submit.prevent="customHandler($event)">
    <button type='submit'>Save</button>
    <button type='submit'>Change</button>
</form>
…Could have the following control logic in its handler method:
customHandler(event) {
    if (event.submitter.innerHTML == 'Save') {
        // Save user data
    } else if (event.submitter.innerHTML == 'Change') {
        // Change user data in different way than 'Save'
    } else {
        // Do nothing
        // The CMultiSelect's 'Select all options' event will fall here
    } 
}
What did we learn?

Since this issue took about 3 cumulative workdays out of my schedule I figured the post I made about it should carry the same weight. I know this is overkill but if even one other developer can avoid the same problem then it’ll have been more than worth it. I would say I learned that JavaScript is so much more complicated than I thought imaginable, yet frustratingly stupid at the same time, but that would mean that I didn’t know that before…

Leave a comment