We help IT Professionals succeed at work.

Open CSS modal from PHP generated table row

Tom Lobb
Tom Lobb asked
on
Medium Priority
48 Views
Last Modified: 2020-02-22
I open a modal by clicking on a button that's in a table. There's one of these buttons in each row. The modal is intended to provide a way of editing the data for the user in the row containing the button that was clicked. The modal opens, but how do I:

1. initiate the JS for the modal's edit process
2. pass the id from the row to JS
3. set the focus on the first input text box
4. I plan to use JS to confirm the delete request as well

I'm fine to use AJAX for updating tables. I've nearly got all the mechanics of the application working without using JQuery, Bootstrap or any other libraries and would like to keep it that way. This is likely the only Web app that I'll ever write and requiring more work is acceptable. I read that the <dialog> element isn't supported by Edge or IE, so that's not an option. Thank you for any assistance that you can provide.
sampleModal.php
Comment
Watch Question

CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
Hey Tom,

Out of interest, is there a reason why you want to avoid the libraries such as Bootstrap / jQuery. There's nothing wrong with that, but you're going to spend way longer writing you code. You'll basically be writing a lot of Javascript and CSS just to re-invent the wheel.
Tom LobbAccess developer / 1 web App

Author

Commented:

I just wanted to keep it as simple as possible and I don't expect that they'd be needed very much. Based on a career of traditional programming, I believe my application is extremely simple, compared to most (it's data entry). Most of what I've learned is self taught, plus the internet. But a lot of what's on the internet doesn't explain things within a global context, so you have to do more research anyway. I guess I feel that I'd rather spend my time developing than learning a couple more libraries.

CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
OK, fair enough.

I'm not going to give you any specifc code examples as I use Bootstrap / jQuery etc and to try this with just CSS and Javascript would just take me too long :)

You say it's fairly simple, but even something like this has quite a few moving parts (CSS / HTML / Javascript / PHP)

There are a few different ways to handle it. You're already pulling in the data from your database, so you can either use that for just display purposes and pull the data from the DB when you want to edit the User (make an AJAX request to your server based on the User ID from the button you've clicked), or you can store that data within each row to be used to populate the Edit Form in the modal Element. HTML5 has the data attribute which you can store infomation in, so in your case, you could store the whole user within the button:

<a id='useredit' href='#modal-editUser' data-user='{json_encode($user)}' class='form-button'>Edit</a>

What this means is that you can retrieve that information when you click on the button. You'll need to code your click handler to read the data-user attribute, extract the properties from the User object, populate your Edit Form and then show the Modal.

You'll then need to code the submit handler of the form in your Modal to make an AJAX POST request back to your server (normally you'd want to handle data validation at the client-side with Javascript and at the server-side with PHP). Your server-side script will save the info to the database and generate a response to send back to your page. This could be a simple success token, or it could be a fulll. fresh copy of the data. Either way, you'll then need to update the row on your page to reflect the changes made to the DB. Once that's complete, you'll need to close down your Modal.

Sorry I can't give you more specifics but I gave up doing things this way a long time ago :)
Tom LobbAccess developer / 1 web App

Author

Commented:

Thanks Chris. I'll see what I can accomplish with what you've given me. If I want to try Bootstrap/jQuery, can you give me a brief description of how I would use them in my situation. Can you load just the parts of the libraries that you're going to use or do you have to load the whole thing?

CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
Commented:
Hey Tom,

With regard to loading just the parts you want - technically, yes you can, but you're stepping into the realm of build tools. As you're just starting out with the librares I wouldn't suggest you go down that route. Even if you did, it's kind of counter-productive. When we include the bootstrap and jQuery libraries, we often include them from a Content Delivery Network. Given their popularity, this means that when a use visits your site, there's a very high chance that they already have the libraries in their cache, so they're very quick to load. If you build you're own version, they wouldn't have them in cache so would have to download your speciifc version directly, which is lkely to be slower than from the CDN.

Bear in mind that the minified version of jQuery comes in at about 30k, Bootstrap CSS comes in at 23k and Bootstrap JS comes in at 15k - so that's less the 70k, pulled from cache!

Anyway, here's a quick demo of the approach I'd start with, Using Bootstrap for the Layout and Modal, plus jQuery for the Behavior. Probably easiest if I show you some code, you have a read through it, and come back to me with any questions:

First, the main HTML Page. In my example, I've just generated some dummy data, but in your case, you'd retrive those from the database
<?php 
// Make sure we can see any errors
error_reporting(E_ALL);
ini_set('display_errors', 1);

// Generate some dummy data
require_once 'UserFactory.php';
$userFactory = new UserFactory();
$users = $userFactory->CreateUsers(10);
?>
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Chris Stanyon // EE - 29173341</title>
        
        <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
        <script src="myScript.js"></script>    
    </head>
    <body>
        <!-- The Users Table -->
        <div class="container mt-2 mb-2">
            <div class="row">
                <div class="col-md-12">
                    <table class="table">
                    <?php foreach ($users as $user): ?>
                        <tr data-user='<?= json_encode($user) ?>'>
                            <td class="firstname"><?= $user['firstName'] ?></td>
                            <td class="lastname"><?= $user['lastName'] ?></td>
                            <td><button class="edit btn btn-success">Edit</button></td>
                        </tr>
                    <?php endforeach; ?>
                    </table>
                </div>
            </div>
        </div>

        <!-- The Modal Form -->
        <div id="editModal" class="modal" tabindex="-1" role="dialog">
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">Edit User</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body">
                        <form id="editUser">
                            <input type="hidden" id="userId" name="userId" value="">
                            <div class="form-group">
                                <label for="firstName">First Name</label>
                                <input type="text" class="form-control" id="firstName" name="firstName">
                            </div>
                            <div class="form-group">
                                <label for="lastName">Last Name</label>
                                <input type="text" class="form-control" id="lastName" name="lastName">
                            </div>
                        </form>
                    </div>
                    <div class="modal-footer">
                        <button type="button" id="save" class="btn btn-primary">Save changes</button>
                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                    </div>
                </div>
            </div>
        </div>

    </body>
</html>

Open in new window

Now for the Javascript part of it (myScript.js). It just has two event bindings. The first one is bound to the Edit button and is responsible for retrieving the data-user property, populating the Modal Form Fields and showing the Modal. The second handler is fired when the Save button on the Modal is clicked. It sends the form data, via an AJAX request to the server for processing (saving teh record to a DB?). When it returns, it updates the data displayed in your table and closes the modal:

$(function() {

    let currentRow = null; 

    $('.edit').click(function(e) {
        // Remeber the current row
        currentRow = $(this).closest('tr');
        // Get the current user
        let user = currentRow.data('user');
        // Populate the modal
        $('#userId').val(user.id);
        $('#firstName').val(user.firstName);
        $('#lastName').val(user.lastName);
        // Show the Modal
        $('#editModal').modal();
    });

    $('#save').click(function(e) {
        $.ajax({
            url : 'saveUser.php',
            method : 'post',
            data : $('#editUser').serialize(),
            dataType : 'json',
        }).done(function(res) {
            if (res.success) {
                $('.firstname', currentRow).text(res.user.firstName);
                $('.lastname', currentRow).text(res.user.lastName);
                currentRow.data('user', res.user);
            } else {
                alert("There was an error!");
            }
        }).always(function() {
            $('#editModal').modal('hide')
        });
    });
});

Open in new window

We can see from the done() method of the AJAX handler that the data passed back from the server should have a success property and a user property. You'll need to make sure your PHP script (saveUser.php) generates that and spits out the response as JSON. Here's a quick example, but without the DB saving bit:

<?php
// Get the data that's been POSTed to the server. 
// Normally you add some validation and sanitisation in here
$userId = $_POST['userId'];
$firstName = $_POST['firstName'];
$lastName = $_POST['lastName'];

// Now you would save the record to your DB:
// Make sure you use a Parameterisd Statement to prevent SQL Injection
// UPDATE userTable SET firstName = ?, lastName = ? WHERE id = ?

// Create a user to be sent back to the server
$user = [
    'id' => $userId,
    'firstName' => $firstName,
    'lastName' => $lastName,
];

// Generate the response to be sent back
$response = [
    'success' => true,
    'user' => $user,
];

// Send back the response as JSON
echo json_encode($response);

Open in new window

They're the main moving parts you'd want in your application. An HTML/CSS page to display the data, the Modal provided by BootStrap, the User Interaction provided by jQuery, and PHP to handle the server-side processing.

Hope that all make sense :)
Tom LobbAccess developer / 1 web App

Author

Commented:

Thanks very much. I'll give it a try.

Tom LobbAccess developer / 1 web App

Author

Commented:

Now I have to see how I can merge it with what I've already done. Is there a way to use the CSS file that I've already written with the Bootstrap CSS file? Can I use this method with just the modals that I've got, or do I have to change my whole application?