Jump to content

Display error inside modal


I-AM-OBODO

Recommended Posts

hello all.

i dont know if to post this here or javascript/ajax section. if its not the right place, please let me know so i can ask in the right place.

i am trying out saving to db via modal form. i learned the basics of using ajax to save data with the modal. so far, i can perform a CRUD via modal but the problem i am having is displaying duplicate entry error inside the modal. I have tried so many ways and the closest i come is displaying error only if a field is duplicate cos i use same trigger as my validation error notice. I'd be glad if i am shown the way to get it to display the error or a better way of getting it done. PS: I want the errors displayed inside the modal. I want the database query error to display where the success message is displayed (i.e on the modalMessage div)

Thanks

My Modal

<div class="modal fade" id="armsModal" data-bs-backdrop="static" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header modal-bg">
<h5 class="modal-title w-100 text-center mb-3" id="exampleModalLabel4">Add School Arms</h5>
<button
type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>

<form id="submitForm" class="myForm">
<div class="modal-body">
  <div id="modalMessage"></div>
      <div class="mb-3">
      <label for="armsname" class="form-label">Arms FullName:</label>
      <input type="text" class="form-control" id="arms_long_name" name="arms_long_name" autocomplete="off" value="<?php if(isset($_POST['arms_long_name'])){ echo $_POST['arms_long_name']; } ?>">
      <span id="longNameError" class="text-danger"></span>
      </div>
      

      <div class="mb-3">
          <label for="armsshort" class="form-label">Arms ShortName:</label>
          <input type="text" class="form-control" id="arms_short_name" name="arms_short_name" autocomplete="off" value="<?php if(isset($_POST['arms_short_name'])){ echo $_POST['arms_short_name']; } ?>">
          <span id="shortNameError" class="text-danger"></span>
      </div>
</div>
<div class="modal-footer modal-bg">
<button type="button" class="btn btn-outline-light btn-sm" data-bs-dismiss="modal">
Close
</button>
<button type="submit" class="btn btn-dark btn-sm">Submit</button>
</div>
</form>
</div>
</div>
</div>

My script

<script>
  //Modal
$('#submitForm').submit(function(event) {
        event.preventDefault();
        
        $("#armsModal").on("hidden.bs.modal", function() {
        $('#longNameError').text('');
        $('#shortNameError').text('');
        $("#submitForm")[0].reset();
        });

        $('#armsModal').on('hidden.bs.modal', function () {
        // Clear form fields
        $('#submitForm')[0].reset();

        // Clear error messages
        $('.invalid-feedback').text('');
        });
        
        // Get form data
        var formData = {
            'arms_long_name': $('#arms_long_name').val(),
            'arms_short_name': $('#arms_short_name').val()
        };
        
        // AJAX request
        $.ajax({
            type: 'POST',
            url: 'school-arms-action.php',
            data: formData,
            dataType: 'json',
            encode: true
        })
        .done(function(data) {
            if (!data.success) {
                if (data.errors.arms_long_name) {
                    $('#longNameError').text(data.errors.arms_long_name);
                }
                if (data.errors.arms_short_name) {
                    $('#shortNameError').text(data.errors.arms_short_name);
                }
            }else{
  

                    modalMessage.innerHTML = '<div class="alert alert-success text-center text-black">ARMS SAVE SUCCESSFUL!</div>';
   
                    setTimeout(function() {
                        window.location.href = 'school-arms';
                    }, 2000); // 2 seconds delay                
            }
        });
    });
</script>

 

My school-arms-action.php

$response = array('success' => false, 'errors' => array());

if ($_SERVER['REQUEST_METHOD'] === 'POST') {

    $arms_long_name = ucwords($_POST['arms_long_name']);
    $arms_short_name = strtoupper($_POST['arms_short_name']);
    $arms_id = mt_rand(100, 999);

    // Validation
    if (empty($arms_long_name)) {
        $response['errors']['arms_long_name'] = 'Arms LongName is Required.';
    }
    if (empty($arms_short_name)) {
        $response['errors']['arms_short_name'] = 'Arms ShortName is Required.';
    }


    // If no errors, proceed to submission
    if (empty($response['errors'])) {

    try {

        $pdo = new PDO("mysql:host=localhost;dbname=db_name", "username", "password");
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        $table=$pdo->query("ALTER TABLE tbl_school_arms AUTO_INCREMENT = 1");
        $table->execute();

    $stmt = $pdo->prepare("

    SELECT * 
    FROM tbl_school_arms 
    WHERE arms_name_long = :arms_name_long 
    OR arms_name_short = :arms_name_short

    ");

    $stmt->bindParam(':arms_name_long', $arms_long_name, PDO::PARAM_STR);
    $stmt->bindParam(':arms_name_short', $arms_short_name, PDO::PARAM_STR);
    $stmt->execute();
    $existingEntry = $stmt->fetch(PDO::FETCH_ASSOC);

    if ($existingEntry) {
        //This is what i used but not the right thing i want
         $response['errors']['arms_long_name'] = 'Duplicate Entry';

    } else {

    // Perform database operations using PDO
    $stmt = $pdo->prepare("

    INSERT INTO tbl_school_arms (arms_id, arms_name_long, arms_name_short) 
    VALUES (:arms_id, :arms_name_long, :arms_name_short)");

    $stmt->bindParam(":arms_id", $arms_id);
    $stmt->bindParam(":arms_name_long", $arms_long_name);
    $stmt->bindParam(":arms_name_short", $arms_short_name);
    $stmt->execute();

    if($stmt->rowCount()){

    $response['success'] = true;

    }
 
}
} catch (PDOException $e) {
            echo "Error: " . $e->getMessage();
        }
    }  

}

echo json_encode($response);

 

Link to comment
Share on other sites

if both arms_name_long and arms_name_short must be unique, you would want to detect which one or both are duplicates and display a separate and specific message in the appropriate span tag(s).

as to how to do this, your database design must enforce uniqueness. both of those database table columns should be defined as unique indexes. you would then just attempt to insert the row of data and in the exception error handling, detect if a duplicate index error number (1062) occurred. It is at this point where you would build and execute a SELECT query to find which of the values are duplicates.

here's a laundry list of things you should/should not be doing in this code -

  1. the for='...' attribute in the <label ...> tag must match the corresponding form field's id='...' attribute OR if you put the closing </label> tag after the form field, you can leave out the for='...' attribute entirely and if not used for anything else, leave out the id='...' attribute.
  2. for problems like item #1, you need to validate your resulting web pages at validator.w3.org
  3. any value you output in a html context needs to have htmlentities() applied to it to help prevent cross site scripting.
  4. if you use the null coalescing operator (??), it will simplify things like the value='...' attribute logic - value='<?=htmlentities($_POST['arms_long_name']??'',ENT_QUOTES)?>'
  5. the ids you use in a database context should be generated via autoincrement primary index columns, not using php random numbers. if you did have some need to generate unique random numbers and store them in a database table, you would need to insure uniqueness by defining the column holding them as a unique index and perform a duplicate index error check as described above for the arms_name_long and arms_name_short values.
  6. you should keep the form data as a set in a php array variable, then operate on elements in this array variable throughout the rest of the code.
  7. you should trim all input data before validating it, mainly so that you can detect if values where all white-space characters. once you do item #6 on this list, you can trim all the data at once using a single php array function.
  8. you should apply any ucwords() and strtoupper() modification to values only when you output them.
  9. the value you output in the form field value='...' attribute should be the trimmed, validated value, not the raw field value.
  10. when you make the database connection, you need to - set the character set to match your database table's character set, set the emulated prepared query setting to false (you want to run real prepared queries whenever possible), and set the default fetch mode to assoc (so that you don't need to specify it in each fetch statement.)
  11. i'm assuming that the ALTER TABLE... query is temporarily in the code and will be removed? btw - the ->query() method call executes the query. you don't need an additional ->execute() call and i'm not sure what doing so in this case will accomplish.
  12. if you use simple ? prepared query place holders and simply supply an array of input values to the ->execute([...]) call, it will greatly reduced the amount of typing you have to do for each sql query.
  13. as already discussed, you would first attempt to insert the data, then in the exception error handling, detect if the query produced a duplicate index error number. if it did, you would then execute a SELECT query to find which column(s) contain the duplicate values. for any other error number, you would simply rethrow the exception and let php handle it.
  14. you should not output raw database statement errors on a live/public server, as this gives hackers useful information when they internationally do things that trigger errors. if you only catch and handle duplicate (and out of range) database query exceptions in your code, and let php catch and handle all other database exceptions, php will 'automatically' display/log the raw database statement errors the same as its error related settings are setup to do for php errors.
Edited by mac_gyver
Link to comment
Share on other sites

17 hours ago, mac_gyver said:

if both arms_name_long and arms_name_short must be unique, you would want to detect which one or both are duplicates and display a separate and specific message in the appropriate span tag(s).

as to how to do this, your database design must enforce uniqueness. both of those database table columns should be defined as unique indexes. you would then just attempt to insert the row of data and in the exception error handling, detect if a duplicate index error number (1062) occurred. It is at this point where you would build and execute a SELECT query to find which of the values are duplicates.

here's a laundry list of things you should/should not be doing in this code -

  1. the for='...' attribute in the <label ...> tag must match the corresponding form field's id='...' attribute OR if you put the closing </label> tag after the form field, you can leave out the for='...' attribute entirely and if not used for anything else, leave out the id='...' attribute.
  2. for problems like item #1, you need to validate your resulting web pages at validator.w3.org
  3. any value you output in a html context needs to have htmlentities() applied to it to help prevent cross site scripting.
  4. if you use the null coalescing operator (??), it will simplify things like the value='...' attribute logic - value='<?=htmlentities($_POST['arms_long_name']??'',ENT_QUOTES)?>'
  5. the ids you use in a database context should be generated via autoincrement primary index columns, not using php random numbers. if you did have some need to generate unique random numbers and store them in a database table, you would need to insure uniqueness by defining the column holding them as a unique index and perform a duplicate index error check as described above for the arms_name_long and arms_name_short values.
  6. you should keep the form data as a set in a php array variable, then operate on elements in this array variable throughout the rest of the code.
  7. you should trim all input data before validating it, mainly so that you can detect if values where all white-space characters. once you do item #6 on this list, you can trim all the data at once using a single php array function.
  8. you should apply any ucwords() and strtoupper() modification to values only when you output them.
  9. the value you output in the form field value='...' attribute should be the trimmed, validated value, not the raw field value.
  10. when you make the database connection, you need to - set the character set to match your database table's character set, set the emulated prepared query setting to false (you want to run real prepared queries whenever possible), and set the default fetch mode to assoc (so that you don't need to specify it in each fetch statement.)
  11. i'm assuming that the ALTER TABLE... query is temporarily in the code and will be removed? btw - the ->query() method call executes the query. you don't need an additional ->execute() call and i'm not sure what doing so in this case will accomplish.
  12. if you use simple ? prepared query place holders and simply supply an array of input values to the ->execute([...]) call, it will greatly reduced the amount of typing you have to do for each sql query.
  13. as already discussed, you would first attempt to insert the data, then in the exception error handling, detect if the query produced a duplicate index error number. if it did, you would then execute a SELECT query to find which column(s) contain the duplicate values. for any other error number, you would simply rethrow the exception and let php handle it.
  14. you should not output raw database statement errors on a live/public server, as this gives hackers useful information when they internationally do things that trigger errors. if you only catch and handle duplicate (and out of range) database query exceptions in your code, and let php catch and handle all other database exceptions, php will 'automatically' display/log the raw database statement errors the same as its error related settings are setup to do for php errors.

Thank you for your responds and list of dos/don'ts. Will take note of them. But still didn't solve my problem. If I don't use a modal for the form, I can check for duplicate and display the error. The problem I am having is displaying the duplicate error inside the modal.

As for ids, they are required for the modal to work. The id passes values of the form to the database. That's how the code for the modal was built.

The alter table is temporal.

No. I am not outputting the database errors live.

I am not really a fan of placeholders.

I have a function that trims inputs for validation.

Good to know about the ucword/strtoupper. But is there a reason why it should be on output and not during save? Just curious to know.

Overall, the observations are very useful and I have learned a few things that I will adapt to.

If, I can't get a way to display the errors inside the modal, I guess I will just change the design and not use modal for the form.

Thanks

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.