How can I conditionally render a container that's been outputted by PHP with Vue.js?

Viewed 123

I've encountered a problem in which I get data from a database with PHP I then store the data into a PHP array like so :

$query = mysqli_query($db, "SELECT id, name, description, experience, focus, fileformat, file, edit FROM trainers;");
$i = 0;
while($query_run = mysqli_fetch_assoc($query)){
    $id = $query_run['id'];
    $name = $query_run['name'];
    $description = $query_run['description'];
    $experience = $query_run['experience'];
    $focus = $query_run['focus'];
    $format = $query_run['fileformat'];
    $file = $query_run['file'];
    $edit = $query_run['edit'];
    $edit = explode(' ', $edit);
    $trainers_meta[$i] = array('Id' => $id, 'Name' => $name, 'Description' => $description, 'Experience' => $experience, 'Focus' => $focus, 'Fileformat' => $format, 'File' => $file, 'Edit' => $edit);
    $i++;
}

Afterwards I display the data from the array in the HTML code using a PHP foreach loop like so :

<div class="container-lg px-lg-4 px-0 pt-3 border-right border-left border-bottom border-radius-bottom mb-5">
    <?php foreach ($services_meta as $service):?>
        <div class="container-lg bg-dark-white py-3 px-3 my-3 border-radius">
            <form action="admin.php" method="post" enctype="multipart/form-data">
                <div class="row no-gutters">
                    <div class="col-lg-5 col-12 d-flex align-items-center">
                        <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"><?php echo $service['Name']?></h5>
                    </div>
                    <div class="col-lg-5 col-8 d-flex align-items-center pt-lg-0 pt-md-3 pt-sm-2 pt-1">
                        <h6 class="font-normal text-brand-primary pr-1">Úprava :</h6>
                        <h6 class="text-truncate"><?php echo $service['Edit'][0]?> <?php echo $service['Edit'][1]?></h6>
                    </div>
                    <div class="col-lg-2 col-4 d-flex align-items-center justify-content-end">
                        <button class="btn btn-brand-secondary font-bold px-22 py-2 mx-1" type="submit" name="services-submit-<?php echo $service['Id']?>"><i class="fas fa-edit"></i></button>
                        <button class="btn btn-brand-primary font-bold px-3 py-2 mx-1" type="submit" name="services-delete-<?php echo $service['Id']?>"><i class="fas fa-trash-alt"></i></button>
                    </div>
                    <div class="col-12"><hr></div>
                    <div class="col-lg-4 col-md-6 col-12 justify-content-md-start justify-content-center pb-md-2 d-flex align-items-center pb-lg-3">
                        <div class="d-flex flex-column pt-3">
                            <h6 class="font-normal text-brand-primary pb-1">Popis :</h6>
                            <textarea type="text" name="services-description-<?php echo $service['Id']?>" class="border-radius" cols="18" rows="4"><?php echo $service['Description']?></textarea>
                        </div>
                    </div>
                    <div class="col-lg-4 col-md-6 col-12 justify-content-md-start justify-content-center pb-md-2 d-flex pb-lg-3">
                        <div class="d-flex flex-column pt-3">
                            <h6 class="font-normal text-brand-primary pb-1">Místo :</h6>
                            <input type="text" name="services-place-<?php echo $service['Id']?>" class="border-radius" value="<?php echo $service['Place']?>">
                        </div>
                    </div>
                    <div class="col-lg-4 col-md-6 col-12 justify-content-md-start justify-content-center pb-md-2 d-flex pb-lg-3">
                        <div class="d-flex flex-column pt-3">
                            <h6 class="font-normal text-brand-primary pb-1">Termíny :</h6>
                            <input type="text" name="services-terms-<?php echo $service['Id']?>" class="border-radius" value="<?php echo implode($service['Terms'])?>">
                        </div>
                    </div>
                    <div class="col-lg-4 col-md-6 col-12 justify-content-md-start justify-content-center pb-md-2 d-flex align-items-center pb-lg-3">
                        <div class="d-flex flex-column py-3">
                            <h6 class="font-normal text-brand-primary pb-1">Název :</h6>
                            <input type="text" name="services-name-<?php echo $service['Id']?>" class="border-radius" value="<?php echo $service['Name']?>">
                        </div>
                    </div>
                </div>
            </form>
        </div>
    <?php endforeach;?>
</div>

As you may've noticed I use the Id of the data row from the MySQLi database which it originates from to provide a unique name attribute which I can then use to filter through the $_POST of each of the containers so that I can provide functions like deleting from the database on a press of the button which is contained within each container. Here's an example of the delete function for a specific container :

if($_SERVER['REQUEST_METHOD'] == 'POST'){
    $id = $trainer['Id'];
    foreach ($trainers_meta as $trainer){
        if(isset($_POST["trainers-delete-$id"])){
            $stmt = $db -> prepare("DELETE FROM trainers WHERE id = ?;");
            $stmt -> bind_param("i", $id);
            $stmt -> execute();
        }
    }
}

I simply loop through each of the IDs from the database with $_POST and check which one has been set. This is important because the user also has the ability to add a new container and fill it with new data after they do so I have to check dynamically for the results from the database since they change overtime and I cannot simply hardcore a specific name attribute for use with $_POST.

My actual problem is that I am looking for a way to implement AJAX like functionality to the webpage so that immediatelly upon clicking delete for instance that specific containers disappears without the requirement for the user to refresh the page. I am trying to use Vue.js as my JavaScript library for the entire project.

Vue.js provides an option for conditional rendering with the v-if attribute that's provided in the page's HTML but my problem is that I seem to have no way of determining the variable that sets the visibility of the element to false because if I would simply add a v-if and then set the trainersVisibility variable in Vue.js JavaScript to false like :

let app = Vue.createApp({
    data: function(){
        return{
            vue_init: 'Vue initialization success',
            trainersVisibility: true //This would be set to false on the button click
        }
    }
})
app.mount('#app')

all the containers disappear instead of a specific one. I got an idea of simply echoing the Id from the results array with v-if="trainersVisibility-<?php echo $trainer['Id']?>" directly into the v-if attribute but that should throw an error because the base variable was never defined in the Vue.js JavaScript file at all and it's only occured in the PHP file within it's HTML code. I cannot simply define multiple v-if boolean variables for each container because I have no way of knowing how much containers with adequate data exist on the page since the number of them changes overtime. What can I do to use conditional rendering for each container sepparately for it to allow me to properly setup AJAX like functionality? I am very new to Vue.js so I'm very sorry if this is obvious to You but it's a little messy for me still. Huge thanks for any help with this issue from anybody!

Edit :

As per the comments of this question I was lead to the conclusion of converting the database array with the results into a JavaScript array and then do the rest with JavaScript only. That requires the use of the json_encode() function inside of PHP for later use in JavaScript. However json_encode was not completed properly. This was indded like I mentioned caused by the BLOB data that was contained within the array. The problem was that the BLOB data was converted to base64 only once it's been rendered in the HTML code where I used the PHP base64_encode(); function. And so now I convert to base64 directly in the PHP loop which stores the data into the array intially. Once converted to base64 BLOBs appear to be JavaScript compatible. The conversion now runs without errors and I can echo out the JSON array using PHP and it is indeed of a JSON format.

I've tried defining the variable inside of a and set it to the JSON converted value as a JavaScript variable both in the included PHP file which scrapes the data from the MySQLi database as well as the index file itself. No matter the file I put the tag in or the position I put the tag in altough the variable exists Vue.js never sees it at all and so I'm unable to do anything with the saved data. I was trying to look for a solution but haven't found any way to parse a pure JavaScript variable to Vue.js. If there is any way this could be done I'm not aware of it. Guess I might have to switch to a completely different JavaScript framework just because of this...

0 Answers
Related