简体   繁体   中英

How do I handle multiple @click events in a single <form> with @submit.prevent in Vue.js?

I have a Vue.js project with a form in which I submit data using @click events into a database using Axios as well as display the change using AJAX.

This is the form:

<div class="container-fluid px-0" v-for="(service, i) in servicesMeta">
    <div v-if="i == 0" :class="'pt-lg-4'"></div>
    <div class="container-lg bg-dark-white py-3 px-3 border-radius">
        <form action="admin.php" @submit.prevent="editData('services', service.Id, i, 'edit'), deleteData('services', service.Id, i, 'delete')">
            <div class="row no-gutters">
                <div class="col-md-9 col-12 d-flex align-items-center pb-md-0 pb-2">
                    <i class="fas fa-code-branch mr-3 ml-2 text-brand-primary" style="font-size: 1.9em"></i>
                    <h5 class="font-bolder text-truncate pr-md-0 mr-4">{{service.Name}}</h5>
                </div>
                <div class="col-md-3 col-12 d-flex align-items-center justify-content-end">
                    <button class="btn btn-brand-secondary btn-services font-bold py-1 mx-1" @click="editData('services', service.Id, i, 'edit')"><i class="fas fa-edit"></i></button>
                    <button class="btn btn-brand-primary btn-services font-bold py-1 mx-1" @click="deleteData('services', service.Id, i, 'delete')"><i class="fas fa-trash-alt"></i></button>
                </div>
                <div class="col-12"><hr></div>
                <div class="col-lg-4 col-sm-6 col-12 justify-content-lg-start justify-content-center pb-md-2 d-flex align-items-center pb-lg-3">
                    <div class="d-flex flex-column pt-3 px-3">
                        <h6 class="font-normal text-brand-primary pb-1">Popis :</h6>
                        <textarea type="text" class="border-radius" cols="18" rows="4" v-model="service.Description"></textarea>
                    </div>
                </div>
                <div class="col-lg-4 col-sm-6 col-12 d-flex flex-column justify-content-between align-items-lg-start align-items-center pb-md-2 pb-lg-3">
                    <div class="d-flex flex-column pt-3 px-3">
                        <h6 class="font-normal text-brand-primary pb-1">Místo :</h6>
                        <input type="text" class="border-radius" v-model="service.Place">
                    </div>
                    <div class="d-flex flex-column px-3">
                        <h6 class="font-normal text-brand-primary pb-1">Termíny :</h6>
                        <input type="text" class="border-radius" v-model="service.Terms">
                    </div>
                </div>
                <div class="col-lg-4 col-sm-6 col-12 d-flex flex-column justify-content-between align-items-lg-start align-items-center pb-md-2 pb-lg-3">
                    <div class="d-flex flex-column pb-lg-0 pt-lg-3 pt-sm-4 py-3 px-3">
                        <h6 class="font-normal text-brand-primary pb-1">Jméno :</h6>
                        <input type="text" class="border-radius" v-model="service.Name">
                    </div>
                    <div class="d-flex flex-column px-3 pb-md-0 pb-sm-4">
                        <h6 class="font-normal text-brand-primary pb-1">Cena :</h6>
                        <input type="text" class="border-radius" v-model="service.Price">
                    </div>
                </div>
                <div class="col-lg-4 col-sm-6 col-12 d-flex flex-column justify-content-lg-center justify-content-between align-items-lg-start align-items-center pb-md-2 pb-lg-3">
                    <div class="d-flex flex-column pt-lg-0 pt-sm-4 pt-3 pb-lg-2 px-3">
                        <h6 class="font-normal text-brand-primary pb-1">Sleva :</h6>
                        <input type="text" class="border-radius" v-model="service.Discount">
                    </div>
                </div>
            </div>
        </form>
    </div>
    <div v-if="i != servicesMeta.length - 1" :class="'mb-4'"></div>
    <div v-else :class="'mb-3'"></div>
</div>

I'm using a v-for loop since there is multiple items for which I want to create an individual container with the capability to add, edit and delete data for that specific item. The "trainersMeta" array of objects is generated by getting data from a MySQLi database with PHP on page load and then handing it to Vue.js using PHP's json_encode() method. All of the data is fine and everything works.

In the form I have 2 @click events with handlers:

  1. editData
  2. deleteData

I then handle the data using Vue.js within methods:{} :

methods:{
    editData: function (requestSection, Id, i, handleType){
        if(requestSection == 'services'){
            console.log(handleType);
            axios.post('ajax.php',{
                request: 2,
                Id: Id,
                Name: this.servicesMeta[i].Name,
            })
            .then(function (response) {
                console.log(response);
            })
        }
    },
    deleteData: function (requestSection, Id, i, handleType){
        if(requestSection == 'services'){
            console.log(handleType);
            axios.post('ajax.php',{
                request: 5,
                Id: Id
            })
            this.servicesMeta.splice(i, 1);
        }
    }

The first parameter requestSection is just a string that I use to identify which section of the page is the data submitted from. This is because I have another form with mostly the same structure on the page which I identify with a different string so that I can use the same methods without writing separate ones for each section. Id is simply the id of the row retrieved from the database. i is the loop index which I use to provide the AJAX like functionality. With it I remove the object from the array so that it disappears from the webpage after the delete button is clicked and the request to remove it from the database has been sent.

The problem with the code is that for some odd reason anytime I click the button with @click=deleteData... the method editData is run instead? I've verified and actually instead of request: 5 which relates to the deleteData method the request is set to request: 2 instead and if I change the data in the <input> fields on the page it is actually replaced inside of the database as well as on the page. Just like as if I ran the editData method originally. I've added an additional parameter handleType which I used to identify which event is being run and logged the outpout to the browser's console and got 'edit' so edit was actually run instead of delete. Even worse the code was working just fine only like an hour ago and I was only fiddeling with some CSS in the meantime so I'm totally confused as to what is going on here.

This is the PHP code which handles the AJAX database requests:

//Services edit data
if($request == 2){
    $id = $data->Id;
    $name = $data->Name;
    $stmt = $db -> prepare("REPLACE INTO services (id, name) VALUES(?, ?);");
    $stmt -> bind_param("is", $id, $name);
    $stmt -> execute();
    exit;
}

//Services delete data
if($request == 5){
    $id = $data->Id;
    $stmt = $db -> prepare("DELETE FROM services WHERE id = ?;");
    $stmt -> bind_param("i", $id);
    $stmt -> execute();
    exit;
}

But I believe that the error has nothing to do with the PHP code since invalid request is already being parsed to PHP from the JS. At first I though I figured it out because I only had the editData method in the form's @submit.prevent but strangely even just with editData the code worked flawlessly with no errors/warnings before (I know weird). I've read on a website that you can put two different methods into the <form> @submit so I added the deleteData method to it also which did not make a difference. What is going on here? What am I missing?

I most likely ended up making a small typo probably missing an "s" in one of the section references. I've pulled a backup and redone all the changes and everything appears to work again. Would still be grateful if anybody could clearn up what is the @submit?prevent parameter used for then. I genuinely could not find a proper answer online to it...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM