5

I'm trying to update records in DB without refreshing Form. I have grid.php page with the form to display and update records. Then, I have the file update.php with the UPDATE query. The third file is js1.js with AJAX code. If I map the grid.php to update.php through action=update.php, the update query works great. But as soon as I try to include js1.js file to prevent form refreshing, it stops working.

The code is as following:

grid.php

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="j1.js"></script>
<?php //query.php
    require_once 'header.php';
    if (!$loggedin) die();

    $query = "SELECT SpringMgmt.SpringMgmtID, 
                     SpringMgmt.SpringMgmtActiveYear, 
                     SpringMgmt.PoolID, 
                     SpringMgmt.Notes, 
                     SpringMgmt.SOIEstSubmitted,
                     SpringMgmt.EstAdditional, 
                     SpringMgmt.SOIMeetingScheduled, 
                     Pool.Pool, 
                     Pool.AreaManager, 
                     Employees.EmployeeID, 
                     Employees.FirstName
              FROM SpringMgmt
                   INNER JOIN Pool ON SpringMgmt.PoolID = Pool.PoolID
                   INNER JOIN Employees ON Employees.EmployeeID = Pool.AreaManager ";
    $result = mysql_query($query);
    echo "OK</div>";
    if (!$result) die ("Database access failed0: " . mysql_error());

    //TABLE AND ITS HEADING
    echo '<table id="header" cellpadding="0" cellspacing="0" border="0" >';
    echo "
    <tr> 
    <th>Pool</th>
    <th>Notes</th>
    <th>SO Sent</th>
    <th>Est</th>
    <th>Meet Date</th>
    </tr> 
    ";
    while($record = mysql_fetch_array($result)){
        echo "<form id='myForm' name='myForm'  method=post>";
        echo "<tr>";
        echo "<td >$record[Pool]</td>";
        echo "<td ><textarea size=4 name=Notes rows=3 cols=22>$record[Notes]</textarea> </td>";
        echo "<td style=background-color:><input type=text size=3 name=SOIEstSubmitted value='$record[SOIEstSubmitted]' /></td>";
        echo "<td ><textarea size=4 name=EstAdditional rows=3 cols=12>$record[EstAdditional]</textarea></td>";
        echo "<td style=background-color:><input type=text size=3 name=SOIMeetingScheduled value='$record[SOIMeetingScheduled]' /></td>";
        echo "<td>
              <input type=hidden name='SpringMgmtID' value=$record[SpringMgmtID] />
              <input type=submit name='submit' id='submit' value='Submit' />
              </div></td>";
        echo "</tr>";
        echo "</form>";
    }
    echo "</table>";
?>   

update4.php:

<?php 
    require_once 'header.php';
    if (!$loggedin) die();

    if(isset($_POST['submit'])){
        $UpdateQuery = "UPDATE SpringMgmt 
                        SET    Notes='$_POST[Notes]',
                               SOIEstSubmitted='$_POST[SOIEstSubmitted]',
                               EstAdditional='$_POST[EstAdditional]',
                               SOIMeetingScheduled='$_POST[SOIMeetingScheduled]'
                        WHERE SpringMgmtID='$_POST[SpringMgmtID]'";
        mysql_query($UpdateQuery);
    };
?>

js1.js

$(function () {

    $('form').on('submit', function (e) {

        e.preventDefault();

        $.ajax({
            type: 'post',
            url: 'update4.php',
            data: $('form').serialize(),
            success: function () {
                alert('form was submitted');
            }
        });

    });

});
Alvaro Montoro
  • 28,081
  • 7
  • 57
  • 86
Luke
  • 407
  • 2
  • 10
  • 22
  • Could you indent your code please! – idmean Aug 23 '14 at 19:37
  • Since you are building forms in a loop, you will have `n` number of forms. You do not specify which `form` to serialize in `data: $('form').serialize(),`. – Sean Aug 23 '14 at 20:25
  • 1
    I hope that's not the SQL code that you are using in your project. If it is, **it's subject to SQL injection**. You should read http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php and then rewrite it using MySQLi or PDO and parameterized queries. – Alvaro Montoro Aug 23 '14 at 21:20
  • in addition to Sean's response, I believe (can't check) you should change the line `data: $('form').serialize(),` to `data: $(this).serialize(),` – Jhecht Aug 23 '14 at 21:56

2 Answers2

3

Disclosure: I may sound incredibly patronizing and even mean in my response, please note that it is not my intention. I will show you how to fix the issue, but let me first add some comments about the code above along with some suggestions:

  1. The structure of your HTML is not good: a form shouldn't be wrapping each tr, you should consider using div instead of a table, or a "table inside a form inside a cell" (the code looks as ugly as it sounds). You can read more about a similar case here: Create a HTML table where each TR is a FORM

  2. Your SQL statement is subject to SQL injection. This is bad. Really, really bad. As I mentioned in the comments, consider changing to MySQLi or PDO and using parameterized queries. You can read more about it here: How can I prevent SQL injection in PHP?

  3. Your HTML code is not clean. In general, your page will work because the browser will help, but trust me, that is bad programming: you'll eventually change the code, forget about it, and it will be a mess. From what I see:

    • There are multiple elements with the same ID (all the forms created by the loop).
    • There is incomplete inline CSS (background-color:).
    • Quotes are missing in many places.
    • There are a couple of closing </div> without an opening <div> (this could be OK if the opening div comes from header.php; but even if that was the case, the code would be difficult to maintain)

Finally, the solution. I hope you didn't skip all the text above and jump directly here, because it will really help you not only now but in the future.

Change these two things and your code will work (both in js1.js):

  1. Wrap the function in a $(document).ready so it is executed when the page finishes loading.
  2. Change the data from $("form").serialize() to $(this).serialize(), this way you will be sending only the information from the form with the button that you clicked on (instead of all the forms).

The final code for js1.js would look like this:

$(document).ready(function () {

    $('form').on('submit', function (e) {

        e.preventDefault();
        $.ajax({
            type: 'post',
            url: 'update4.php',
            data: $(this).serialize(),
            success: function () {
                alert('form was submitted');
            }
        });

    });
});
Community
  • 1
  • 1
Alvaro Montoro
  • 28,081
  • 7
  • 57
  • 86
0

Okay, so a few things I'm going to try and help you out with quickly.

Query

Your query is complicated, but I feel needlessly so. I've been doing things with MySQL for quite some time now and I can't recall a situation where I used INNER JOIN in the method you are. A much shorter syntax for your query would therefore be: SQL Aliases

$query = "SELECT s.*, p.Pool, p.AreaManager, e.EmployeeID, e.FirstName
              FROM SpringMgmt as s, Pool as P, Employees as E
              WHERE s.PoolID = p.PoolID AND e.EmployeeID = p.AreaManager ";

HTML

Assuming the HTML in your script is the way you want for it to be shown, here's a few things: you can escape double quotes so that they do not break your code. I would change the code inside your loop to this: Click Here to understand the ".$variable." statements I put in your code

echo "<form id=\"myForm\" name=\"myForm\"  method=\"post\">";
        echo "<tr>";
        echo "<td data-field-id=\"pool\">".$record['Pool']."</td>";
        echo "<td ><textarea data-field-id=\"notes\" size=\"4\" name=\"Notes\" rows=\"3\" cols=\"22\">".$record['Notes']."</textarea> </td>";
        echo "<td style=\"background-color:\"><input data-field-id=\"submitted\" type=\"text\" size=\"3\" name=\"SOIEstSubmitted\" value=\"".$record['SOIEstSubmitted']."\" /></td>";
        echo "<td ><textarea size=\"4\" data-field-id=\"additional\" name=\"EstAdditional\" rows=3 cols=\"12\">".$record['EstAdditional']."</textarea></td>";
        echo "<td style=\"background-color:\"><input data-field-id=\"meetingScheduled\" type=\"text\" size=\"3\" name=\"SOIMeetingScheduled\" value=\"".$record['SOIMeetingScheduled']."\" /></td>";
        echo "<td>
              <input type=\"hidden\" name=\"SpringMgmtID\" value=\"$record[SpringMgmtID]\" />
              <input type=\"submit\" name=\"submit\" id=\"submit\" value=\"Submit\" />
              </div></td>";
        echo "</tr>";
        echo "</form>";

AJAX/Javascript Calls

This is a bit more complicated to explain. The jQuery ajax object success function can accept a few parameters to help you in your request. See this link for more explanation. Jump the section about the .done() function. One of them is the data returned FROM the request. This means that in your update4.php file, if you would output the data to the browser as a JSON object, you could then use that data back on your original page.

$(document).ready(function(){
$('form').on('submit', function (e) {
    e.preventDefault();

    $.ajax({
        type: 'post',
        url: 'update4.php',
        data: $(this).serialize(),
        success: function (data,successText) {
           for(var x in data){
              //Use tree traversing to find the input/text elements that have the data-field-id option equal to the x variable; I can't test it right now so I don't want to have this here.
           }
        }
    });

});

});

Update4.php

As another user pointed out in the comment section, your query here is very prone to SQL Injection. Please follow the link they provided to read more.

Now, assuming you want all of the data returned back, the very last set of lines in your update4.php file should be something close to :

<?php 
  require_once 'header.php';
    if (!$loggedin) die();

    if(isset($_POST['submit'])){
        $UpdateQuery = /*"UPDATE SpringMgmt 
                        SET    Notes='$_POST[Notes]',
                               SOIEstSubmitted='$_POST[SOIEstSubmitted]',
                               EstAdditional='$_POST[EstAdditional]',
                               SOIMeetingScheduled='$_POST[SOIMeetingScheduled]'
                        WHERE SpringMgmtID='$_POST[SpringMgmtID]'"; 
               Don't do this, please use a prepared statement or mysql(i)_real_escape_string() on the data.*/
        $result = mysql_query($UpdateQuery);
        if($result!==false){
              echo json_encode(array(
                     'notes'=> $_POST['Notes'],
                     'submitted'=> $_POST['SOIEstSubmitted'],
                     'additional'=>$_POST['EstAdditional'],
                     'meetingScheduled'=>$_POST['SOIMeetingScheduled']
                  ));
        }
    };

NOTE I do NOT recommend doing this. You should move these $_POST variables into other variables that you have properly sanitized. NEVER assume that your users have no knowledge of web technologies. Always, ALWAYS assume the user is someone who has the malicious intent to steal the data from your database. Therefore, ALWAYS check user-inputted data. The only reason I have set this up is because you seem like you are fairly new to these aspects of web development and with all of the other information I've presented I don't want to overload you and turn you off from web development/design.

Side Note

I would suggest looking up a template engine of some variety. It is generally a better practice to have your display (HTML) and data (PHP) as separate as possible. The only template engines I've used previously were a modified version of PhpBB 3's template engine, and Smarty (which the phpBB team based their template engine on).

Since beginning to type this I've seen another answer posted and read it quickly. I think both of us address slightly different portions of your overall problem, so I will give this post to you as a reference, though I think the other user's answer is a bit better than mine is. I repeat his sentiment though, if I sound condescending or mean, I don't mean to.

Also, as I'm sure someone will or has pointed out to you, get in the habit of using mysqli_* functions as mysql_ will be deprecated (no longer usable) in coming versions of PHP.

Jhecht
  • 4,407
  • 1
  • 26
  • 44