Submit buttons don't work in ajax generated forms.

Colin Brazier
Colin Brazier used Ask the Experts™
on
Hi Experts, me again!!!

Not sure if this has ever worked, but I'm rebuilding it for another site so all the moves etc. may have thrown it off.

Basically, my Edit and Delete buttons are not working on a form.  I click them and nothing happens.

This is on my own machine (xampp) so I can't show a working example.  Or a non-working one for that matter.

But here's the html:

while ($row = $db->fetch_Array($sql_query))
	{
?>
		<form method="post" action="postie.php">
			<tr>
				<td><?php echo html($row['title']); ?></td>
				<td> <input type="hidden" name="hdnID" value='" <?php echo $row['id']; ?> "'/>
					 <input type="submit" name="action" value="Edit" class="button small brown" /></td>
				<td> <input type="submit" name="action" value="Delete" class="button small brown" /></td>
			</tr>
		</form>
<?php
	}

Open in new window


This is generated by an Ajax call:

<script>
function showEvent(str)
{
if (str=="")
  {
  document.getElementById("txtHint").innerHTML="";
  return;
  } 
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
    }
  }
xmlhttp.open("GET","ajax_get.php?q="+str,true);
xmlhttp.send();
}
</script>

Open in new window


Interestingly, when I look at the page using developers tools, the rows containing the buttons appear OUTSIDE the forms (see screenshot)...so I've probably done something stupid but I can't see it for looking.

Just seen something...is this structure OK??

<table>
<form>
    <tr>
        <td>....</td>
    </tr>
</form>
<form>
    <tr>
        <td>....</td>
    </tr>
</form>
</table>

  ColCapture.JPG
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
1. Why so many forms - they are all posting to the same place and if you are doing it via ajax then you don't even need a form in theory.

2. Why are you doing AJAX by building the universe from scratch - why not use jQuery that wraps up all the cross browser pitfalls for you. Even if you are averse to using jQuery in your prod version (not sure why this would be the case) I would still use it to proof the concept and then change over when everything is working.

Going back to your forms if you did something like this
HTML
<form action="t1276.postie.php">
  <table class="table table-striped">
	<tr>
	  <td>new 12 dec</td>
	  <td><button value="154">Submit</button></td>
	</tr>
	<tr>
	  <td>another row</td>
	  <td><button value="154">Submit</button></td>
	</tr>
  </table>
</form>

Open in new window

jQuery
<script>
$(function() {
  $('form button').click(function() {
    $.ajax({
      url: this.form.action,
      type: 'POST',
      data: {id: $(this).val()},
      success: function(data) {
        $('#txtHint').html(data);
      }
    });
    return false;
  });
});
</script>

Open in new window

Working sample here to demonstrate the concept

Author

Commented:
Hi Julian,

I can't answer your questions I'm afraid.  I think i was following a tutorial associated with the calendar widget.  As far as I'm concerned, the simpler the better.

Your example looks great, I'll have a try and get back to you.  

I attach a screenshot of my page, something I omitted in my earlier post.
Capture1.JPG
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Maybe describe what you want to achieve. From the Screen shot looks like you want to edit delete calendar entries.

To better advise I would need to know exactly what you want to happen on Edit and Delete.

I would give each button a class depending on whether it was edit or delete and then hook up an event handler for Edit and one for Delete. Each button in a row has the same value - the id of the event.

When the button is clicked depending on its class either the Edit or Delete EH is called - it is then a simple adaption of the code I posted earlier to handle each situation.
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Author

Commented:
looks like you want to edit delete calendar entries
Exactly.  The user clicks on a date from the calendar and any events are listed below, each with an edit or delete option.  There is an Add button that can add an event for the day, which works fine.

When an "edit" or "delete" button is clicked the form is submitted with the hidden event ID and should go back to a controller page, as I have coded below, but processing never reaches here.

Your solution looks much more promising!

if (isset($_POST['action']) && ($_POST['action'] == 'Edit'))   
{		
      do stuff...

Open in new window

greetings colinspurs, , You say that the submit buttons do not work,, I agree with  Julian  , that you have an incorrect arrangement for the way you use your FORMS, you do not need all of those forms to have all of those "Edit" and "Delete" submit buttons work.
I have found that for <table>, web browsers do NOT allow any thing but spaces, , tabs, , and line-breaks between the table elements of <tr> and <td>, you have this -
 </tr>
</form>
<form>
    <tr>
        <td>....</td>
    </tr>
</form>

Open in new window


To work correctly in a browser you can not have the
</form>
<form>
between the </tr> and the next <tr>, you can not place any tag <span>, between the </tr> and the next <tr>, or it will disrupt the browser's read of the elements, and my just ignore the <form>, so your submit may not work.
A <form> takes the display properties of a <div>, so you may not even need any table to show the many rows of <forms> you have.

Author

Commented:
Yes indeed, it was a bit of a mess.  I've improved it now, just working out how to hang jquery events off the button classes.

<form action="../admin?wh=diary">
        <table id="events_table" class="table-striped">
            <colgroup>
                <col class="event_title"/>  <!-- gives width of 60% -->
                <col/>
                <col/>
            </colgroup>
<?php
			while ($row = $db->fetch_Array($sql_query))
			{
?>
                <tr>
                    <td><?php echo html($row['title']); ?></td>
                    <td><button class="edit_button" value " <?php echo $row['id']; ?> ">Edit</button></td>
                    <td><button class="delete_button" value " <?php echo $row['id']; ?> ">Delete</button></td>
                </tr>
<?php
			}
?>
		</table>
	</form> 

Open in new window


I take your point about no table at all, perhaps an unordered list would work just as well.
you might can just use a DIV for a row,

<div style="margin: 4px;" >
<?php echo html($row['title']); ?>
<button class="edit_button" value " <?php echo $row['id']; ?> ">Edit</button>
<button class="delete_button" value " <?php echo $row['id']; ?> ">Delete</button>
</div>

you can use margins or other style to place the buttons properly in a position in the row <div>
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
just working out how to hang jquery events off the button classes.

You can do like this

$('button.delete_button').click(function() {
   // do your delete here - you can model this function on the one I posted earlier.
   // either post to a different script OR
   // distinguish the action with an action variable
   $.ajax({
         url: this.form.action,
         data: {action: 'delete', id: $(this).val()},
         type: 'POST',
         success: function(data) {
            // handle response here
         });
   });
});

Open in new window


$('button.edit_button').click(function() {
   // do your delete here - you can model this function on the one I posted earlier.
   // either post to a different script OR
   // distinguish the action with an action variable
   $.ajax({
         url: this.form.action,
         data: {action: 'edit', id: $(this).val()},
         type: 'POST',
         success: function(data) {
            // handle response here
         });
   });
});

Open in new window

Alternatively what you can do is give your buttons a custom data attribute that specifies the action

<button data-action="delete" value="154">Delete</button>
<button data-action="edit" value="154">Edit</button>

Open in new window

Now you can use one AJAX function
// GENERIC FUNCTION THAT HANDLES BOTH edit AND delete
// IT USES A CUSTOM data ATTRIBUTE TO PROVIDE THE action
// VALUE
$('form button').click(function() {
   $.ajax({
         url: this.form.action,
         data: {action: $(this).data('action'), id: $(this).val()},
         type: 'POST',
         success: function(data) {
            // handle response here
         });
   });
});

Open in new window

Author

Commented:
Great neat solution but I'm having trouble processing the response.

Should I get values in $_POST['action'] and $_POST['id'] as I would if the form had been submitted in the normal way?  The $_POST array is empty/non-existent.
Most Valuable Expert 2011
Top Expert 2016
Commented:
Here is the "drop-dead simple" example of making an AJAX request with jQuery.  Maybe if you start from here and build up your application a step at a time it will be easier.
http://www.experts-exchange.com/articles/10712/The-Hello-World-Exercise-with-jQuery-and-PHP.html
I Think the code for Jquery  in comment ID: 41353294, should work, BUT in many versions of IE (and some other browsers), the <button> tag is NOT evaluated for a "value" attribute in the Jquery, since it is not primarily an Input.  It seems that this may be used for a button -
    $(this).attr("value")
or switch to a "data-value" attribute, or just combine the two  text data chunks in to a single comma delimited data-ajax (or any other name data-send )
    <button data-ajax="delete,154">Delete</button>

but you should get some $_POST in the PHP,  with the code in ID: 41353294
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
<button> tag is NOT evaluated for a "value" attribute in the Jquery
Works all the way back to IE8 - personally I am not even interested in IE8 let alone earlier - but industry standard has discarded it except in rare circumstances therefore the above argument, for me, does not hold water any more therefore the code can stand as it is.
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
... PS Tested in IE7 (emulation on IE8) - also works.
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Should I get values in $_POST['action'] and $_POST['id'] as I would if the form had been submitted in the normal way?  The $_POST array is empty/non-existent.
Server side processing is no different from normal form submit. Let's see how you have implemented the post in your AJAX - chances are there is a problem there.

With AJAX the console (F12) is your friend. You can examine it for errors AND you can see the results of the POST both request and response - invaluable for determining what is going on between browser and server

Author

Commented:
Ok, I've stripped it down, here's what we have now.

I'm not sure what to put in the Success option!

Client:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>EE 2</title>

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>

<script>
// GENERIC FUNCTION THAT HANDLES BOTH edit AND delete
// IT USES A CUSTOM data ATTRIBUTE TO PROVIDE THE action
// VALUE
$(document).ready(function(){
	$('form button').click(function() {
	   $.ajax({
			 url: this.form.action,
			 data: {action: $(this).data('action'), id: $(this).val()},
			 type: 'POST'
	   });
	});
});
</script>

</head>
<body>

    <form action="post2.php">
        <table id="events_table" class="table-striped">
        
                <tr>
                    <td>First title</td>
                    <td><button data-action="edit" value " 14 ">Edit</button></td>
                    <td><button data-action="delete" value " 14 ">Delete</button></td>
                </tr>
                <tr>
                    <td>Second title</td>
                    <td><button data-action="edit" value "27">Edit</button></td>
                    <td><button data-action="delete" value "27">Delete</button></td>
                </tr>
                <tr>
                    <td>Third title</td>
                    <td><button data-action="edit" value "98">Edit</button></td>
                    <td><button data-action="delete" value "98">Delete</button></td>
                </tr>

		</table>
	</form> 

</body>
</html>

Open in new window


and server:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>POST Fields and Values</title>
</head>
<body>
<?php
if (isset($_POST['action']))// && ($_POST['action'] == 'edit')
{		
	echo "It is set";
}
else
{		
	echo "It is NOT set";
}

echo "<PRE>";
print_r($_POST);
echo "</PRE>";

printArray($_POST);

/*
 * $pad='' gives $pad a default value, meaning we don't have 
 * to pass printArray a value for it if we don't want to if we're
 * happy with the given default value (no padding)
 */
function printArray($array, $pad=''){
     foreach ($array as $key => $value){
        echo $pad . "$key => $value";
        if(is_array($value)){
            printArray($value, $pad.' ');
        }  
    } 
}
?>
</body>
</html>

Open in new window

Most Valuable Expert 2011
Top Expert 2016

Commented:
You might want to change the form method to GET instead of POST.  If you use GET, you can test from the browser address bar.  If you must have POST (for example, you're trying to change the data model) you can always change GET to POST after your tests verify that the server-side script works correctly.

You might also want to ask yourself what all that HTML in the server-side script is supposed to do for you.  If you don't know, get rid of the HTML.  It's almost certainly not useful, since the server-side of an AJAX application does not produce direct browser output.  Typically the server returns a JSON string, a short text fragment or something like that, so it can be interpreted and styled by the JavaScript in the client browser.  The article shows a correct model.

Author

Commented:
I've only changed POST to GET in the Type.  Is that all I had to do?  It remains empty, nothing follows the ? in the URL.

I take your second point, an oversight when creating a new file.  Removed now:
<?php
if (isset($_GET['action']))// && ($_POST['action'] == 'edit')
{		
	echo "It is set";
}
else
{		
	echo "It is NOT set";
}

echo "<PRE>";
print_r($_GET);
echo "</PRE>";

printArray($_GET);

/*
 * $pad='' gives $pad a default value, meaning we don't have 
 * to pass printArray a value for it if we don't want to if we're
 * happy with the given default value (no padding)
 */
function printArray($array, $pad=''){
     foreach ($array as $key => $value){
        echo $pad . "$key => $value";
        if(is_array($value)){
            printArray($value, $pad.' ');
        }  
    } 
}
?>

Open in new window

Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Ok first up your server code is not right - with AJAX we don't send back the header (html / head / body) sections - those are already loaded in the browser. What we send back is entirely dependent on what we want to do once the AJAX call is done.

Options are
1. You receive a status code that allows you to display a status message
2. You receive data to add to your interface
3. You receive a URL to redirect to
4. You receive HTML to insert somewhere on your page.

Based on your server code it looks like you want to replace the calander portion of your page - that is fine - you simply render out that portion and return it as HTML.

In your success function you simply put the returned HTML in the element that currently contains the calendar.

Based on what we are seeing it appears that you are 2 steps down a 100 step process. There is quite a bit of code that is missing from this (or wrong) - you for instance have not demonstrated how you plan to handle the editing. Deleting is relatively straight forward - your markup is also incorrect in that your value attributes are not followed by equal signs
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Here is a sample showing the delete - it is just for mockup so it is not usable but it demonstrates the concept
HMTL - note the markup for the buttons
  <form action="t1280.php">
    <table id="events_table" class="table-striped">
      <tr>
        <td>First title</td>
        <td><button data-action="edit" class="edit" value="14">Edit</button></td>
        <td><button data-action="delete" value="14">Delete</button></td>
      </tr>
      <tr>
        <td>Second title</td>
        <td><button data-action="edit" class="edit" value="27">Edit</button></td>
        <td><button data-action="delete" value="27">Delete</button></td>
      </tr>
      <tr>
        <td>Third title</td>
        <td><button data-action="edit" class="edit" value="98">Edit</button></td>
        <td><button data-action="delete" value="98">Delete</button></td>
      </tr>

    </table>
  </form> 

Open in new window

JQuery
<script>
$(document).ready(function(){
  $('form button').click(function(e) {
    e.preventDefault();
     $.ajax({
       url: this.form.action,
       data: {action: $(this).data('action'), id: $(this).val()},
       type: 'POST',
       success: function(response) {
        $('#events_table').html(response);
       }
     });
     return false;
  });
});
</script>

Open in new window

PHP
<?php
session_start();
$data = array (
  array ('id' => 14, 'title' => 'First Title'),
  array ('id' => 27, 'title' => 'Second Title'),
  array ('id' => 98, 'title' => 'Third Title'),
);
$action = isset($_POST['action']) ? $_POST['action'] : 0;
$id = isset($_POST['id']) ? $_POST['id'] : 0;
echo "[{$id}]";
if ($action == 'delete') {
  foreach($data as $d) {
    if($d['id'] !=  $id) {
      echo <<< HTML
      <tr>
        <td>{$d['title']}</td>
        <td><button data-action="edit" class="edit" value="{$d['id']}">Edit</button></td>
        <td><button data-action="delete" value="{$d['id']}">Delete</button></td>
      </tr>
      
HTML;
    }
  }
}

Open in new window

Sample here.

Note you need to refresh the page after every delete. As you will see in the PHP code the delete works against a static array that is refreshed on each call - in reality this would be a call against a database which would maintain state. As mentioned this is purely for demonstration purposes.

For editing you could consider using the contenteditable attribute on your content blocks to edit them in place and then pickup the blur / input / paste / keyup events to get the data and send to the server - the trick there is getting confirmation from the user to save the change - you would need to show an in place confirm button to confirm the save

Author

Commented:
Once again I thank you guys for the time and effort put into helping me out.

I am trying to give you the relevant info only for fear of providing too much stuff that would only cloud the issue.

Based on your server code it looks like you want to replace the calander portion of your page

When the user clicks edit or delete I want to show them a new page containing more details of the item they are editing, they then make their adjustments and submit that form in the normal way so I need the ID from the edit or delete button to find the right event to show them.  When they have finished editing, processing returns to the controller which runs the SQL and sends them back to the calendar page for the day that they just looked at.

Processing of forms in whichever stage of the process returns to a controller page which examines $_POST and $_GET values to determine where we need to go for the next stage.

I have this working without jQuery in other parts of the application but needed jQuery because of the calendar element (I think!)

I include the part where I was looking for $_POST values containing the event ID and action =  edit, and I attach the whole of the controller page.  

/* **************************************** EDIT AN EVENT ********************************************/
if (isset($_POST['action']) && ($_POST['action'] == 'edit'))   
{		
	$myID = $_POST['hdnID'];
	$sql = sprintf("SELECT id, title, body, event_date FROM events WHERE id = %d", $myID); 
	
	$sql_query = $db->query( $sql ); 
		
	if (!$sql_query)
	{
		$_SESSION['error'] = 'Error fetching item: '.$sql;
		$_SESSION['error'] .= '<br/><br/>You will be redirected to the diary administration page; click OK to continue.';
		header('Location: ../admin/');
		exit();
	}
	
	$row = $db->fetch_Array($sql_query);
	
	$page_title = 'Edit Event';
	$action = 'edit_item';
	$event_date = $row['event_date'];
	$title = $row['title'];
	$body = $row['body'];
	$button = 'Save';
	$news_form_message = '';  
	$disabled = '';   
	
	include(HTML_PATH.DS.'content_header_level_1.html.php');
	include(HTML_PATH.DS.'admin_top.html.php');
	include(HTML_PATH.DS.'event_form.html.php');
	include(HTML_PATH.DS.'admin_bottom.html.php');
	include(HTML_PATH.DS.'content_footer_level_1.html.php');
	exit();
}

Open in new window

diary_control.php
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
When the user clicks edit or delete I want to show them a new page containing more details of the item they are editing, they then make their adjustments and submit that form in the normal way so I need the ID from the edit or delete button to find the right event to show them.
Then that is not an AJAX solution - that is a link with an ID.

Can we go back a bit and revisit why you are doing this with AJAX - from your server post and discussion in your latest post it appears that you are actually wanting to do a post to another page - i.e. the browser goes to that page.

AJAX is for when you want to update elements on a page without doing a page refresh.

Am I understanding things correctly?

Author

Commented:
AJAX is required to list the events of the day the user chooses from the calendar, generating rows with a hidden ID, a submit button named edit and a submit button named delete for the day chosen.  At that stage AJAX is no longer required.  Server processing is then supposed to pick up the $_POST values and run the required SQL based on those.  My main issue is that the $_POST array is empty and I wondered if that was due to it being generated by the AJAX call, which probably caused the confusion.

This is the event page listing.  It has a div #txtHint which holds any events for that day with the buttons.  
<img  id="left_banner_image" src="../../images/cl_bt_20.jpg" border=0>

<div id="f_page_title" class="con_big_normal_blue">Diary Administration</div>
<div id="button_row">
	<ul>
    	<li><form action="../../admin/" method="post">
                <div>
                    <input type="hidden" name="action" value="admin" />
                    <input class="button medium brown" type="submit" value="Admin menu" />
                </div>
            </form>
		</li>
		<li><?php include (HTML_PATH.DS.'logout.html.php'); ?></li>
    </ul>
</div>

<!--<div style="min-height:1080px;"></div>-->
<!--<div id="focl_1" style="width: 90%;" class="con_normal">-->
<div id="event_list_container" class="con_normal infotable">
    <p>Please select a date: </p>
    <form name="form1" id="form1">
		<?php
        //get class into the page
        require_once('calendar'.DS.'classes'.DS.'tc_calendar.php');
        
        //instantiate class and set properties
        $myCalendar = new tc_calendar("date2");
		$myCalendar->setIcon("calendar/images/iconCalendar.gif");
		#$calendar_default_date = explode('-', $event_date);
		#$myCalendar->setDate($calendar_default_date[2], $calendar_default_date[1], $calendar_default_date[0]);
		if(isset($_SESSION['calendar_date']))
		{
			$calendar_default_date = explode('-', $_SESSION['calendar_date']);
			$myCalendar->setDate($calendar_default_date[2], $calendar_default_date[1], $calendar_default_date[0]);
		}
		else
		{
			$myCalendar->setDate(date('d'), date('m'), date('Y'));
		}
        $myCalendar->setPath("calendar/");
        $myCalendar->setYearInterval(2011, 2020);
        $myCalendar->dateAllow('2011-01-01', '2020-12-31', false);
        $myCalendar->startMonday(true);
        $myCalendar->setOnChange("showEvent(document.form1.date2.value)");  
        //output the calendar
        $myCalendar->writeScript();	  
        ?> 
    </form><br />
    <script>showEvent(document.form1.date2.value)</script>   <!-- Makes ajax call via content_header_level_1.html.php -->
    <a class="button small brown" href="?add">Add</a>
    <br />
    <div id="txtHint" class="events_container">&nbsp;</div>
</div> <!-- end div focl_1  -->

Open in new window

The showEvent(document.form1.date2.value lines call this showEvent script:
<script>
function showEvent(str)
{
if (str=="")
  {
  document.getElementById("txtHint").innerHTML="";
  return;
  } 
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
    }
  }
xmlhttp.open("GET","ajax_get.php?q="+str,true);
xmlhttp.send();
}
</script>

Open in new window


xmlhttp.open("GET","ajax_get.php?q="+str,true); references this code to generate the form HTML:
<?php    
require_once("../includes/initialise.php");
include_once(LIB_PATH.DS.'magicquotes.inc.php');
require_once(LIB_PATH.DS.'access.inc.php');

$event_date = $_GET["q"];

$sql = sprintf("SELECT id, title FROM events WHERE event_date = '%s' ORDER BY id", $event_date);
$sql_query = $db->query( $sql ); 
#echo $sql;
if($db->num_rows($sql_query)==0)
{
	$format_date = date("j F Y",strtotime($event_date));
	echo "<h1>There are no events listed for ".$format_date."<h1>";
	$_SESSION['calendar_date'] = $event_date;
}
else
{
	$format_date = date("j F Y",strtotime($event_date));
?>
	<h1>Events listed for <?php echo $format_date; ?></h1>
    
    <form action="post2.php">
    <!--<form action="">-->
        <table id="events_table" class="table-striped">
            <colgroup>
                <col class="event_title"/>  <!-- gives width of 60% -->
                <col/>
                <col/>
            </colgroup>
<?php
			while ($row = $db->fetch_Array($sql_query))
			{
?>
                <tr>
                    <td><?php echo html($row['title']); ?></td>
                    <td><button data-action="edit" value " <?php echo $row['id']; ?> ">Edit</button></td>
                    <td><button data-action="delete" value " <?php echo $row['id']; ?> ">Delete</button></td>
                </tr>
<?php
			}
?>
		</table>
	</form> 
<?php
	$_SESSION['calendar_date'] = $event_date;
}
?>

Open in new window


and as I say when that form is submitted I'm left with an empty $_POST array.
OK, Been lookin at this question for a while oouchh, , , , So I did my version of the way I might set this page up to work, I do not have colinspurs database, so I did not do any SQL for this, below is the PHP page code for the calender and Event rows display. I do NOT use a <form> in this , since this is all about Ajax and button clicks.  I use a <div> ( well actually a <p> ) for the event ROW with column display for the buttons. I have separated OUT the Parts of the Jquery Ajax javascript, in the script on this page, so hopefully the separate part  will be more understandable than the jumble collection that Jquery likes to use in its shortened code examples.

<?php ini_set("display_errors",1); 
error_reporting(E_ALL);

// I DO NOT have your database, so I do an ARRAY of event title , id  pairs
$rows= array(
  array('title' => 'footy', 'id' => '150'),
  array('title' => '2nd, Game Day, 10:00 am', 'id' => '151'),
  array('title' => '4th, Eat Lunch, 12 noon', 'id' => '152'),
  array('title' => '7th, Circus Show, 8:30 pm', 'id' => '153'),
  array('title' => '10th, Tree Chime Compition, 9:15 am', 'id' => '154'),
  array('title' => '19th, Turkey Call Awards, 7:00 pm', 'id' => '155'),
  array('title' => '25th, Dance School Show, 2:00 pm', 'id' => '156')
  );

$eventMonth = 'December 2015';
?><!doctype html>
<html><head><title>calender post</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<style>
body{background:#e3f7ff;}

.title1 {
  font-size: 136%;
  font-weight: bold;
  text-align: center;
  margin: 6px;
  }

.events{
  border: 6px ridge #db6;
  width: 32.5em;
  background: #ffed99;
  padding-top: 6px;
  padding-left: 6px;
  border-radius: 16px;
  margin: 4px;
  }
  
.events p {
  margin: 6px;
  border-bottom: 1px solid #cfbd69;
  padding: 2px;
  }
  
.events b {
  display: inline-block;
  width: 22em;
  border-right: 1px solid #cfbd69;
  }
  
.events button {
  margin-left: 15px;
  background: #c40;
  background: -webkit-linear-gradient(#c40, #eb8, #c40);
  background: -o-linear-gradient(#c40, #eb8, #c40);
  background: linear-gradient(#c40, #eb8, #c40);
  border-radius: 7px;
  cursor: pointer;
  font-size: 90%;
  }
  
.events button:hover {
  border-color: #fb9;
  background: #eb8;
  background: -webkit-linear-gradient(#eb8, #c40, #eb8);
  background: -o-linear-gradient(#eb8, #c40, #eb8);
  background: linear-gradient(#eb8, #c40, #eb8);
  }
</style>

<script>

$(function() { // Jquery OnLoad function

$("#events1 button").click(function() { // Button onClick event

/*
To Make the Jquery AJAX compounded shortened code
easier to understand the several many PARTS og Ajax operations. .
Ihave separated the several Parts into sections that can be
understood as separate base-code AJAX requirements
*/

// ajxPost is the POST header text parts, in a JS object
// the obj property is the Post "name" the value is post value
var ajxPost = {
  opp: $(this).text(), 
  id: $(this).parent().attr("id").substring(1)
}
//  alert("button click "+ ajxPost.opp+" "+ ajxPost.id.substring(1));

// ajxSend are the Jquery OPTIONS as a JS object
var ajxSend = {
  type: "POST",
  url: "postie.php",
  data: ajxPost,
  timeout: 2500 // To me it is important to have an ajax timeout
  }

// below is the single simple jquery Ajax fuction
var aj = $.ajax(ajxSend);

// below I have the two Ascyncronus ajax responce functions done and fail
 aj.done(function( received ) {
// IMPORTANT, you need to understand what should be SENT and RECEIVED by ajax
//alert(aj.responseText); // turn on this alert for debug of the recieved
  $('#ajReturn').html('POST AJAX return=<br />'+received);
  });
	
  
// this is the Ajax fail function, but it's so complicated that few have figured out how to use it
  aj.fail(function(xhr, error1, err) {
  if (xhr.status==404) alert("ERROR from Ajax as '404 status' the "+ajxSend.url+" page was NOT on Server, \nCan NOT recover from this ERROR, This operation is NOT available!");
  else {
  alert("Ajax ERROR = \""+error1+"\", with server Status: "+xhr.status+", post-URL: "+ajxSend.url+", \npost-Data: "+ajxSend.data+", \nerror because: "+err);
  if (aj.responseText) {
    $('#ajReturn').html(aj.responseText); 
    }else $('#ajReturn').html("Ajax Received Text is empty");
  }
  });

});
});// end $(function()
</script>
</head>
<body><h3 style="text-align:center;">calender post development</h3>
<div style="width: 200px; height: 200px; border: 2px dashed #4a6;">Calender</div>
<p>
<button>ADD</button>
</p>
<div id="events1" class="events">
<div class="title1">Events Listed for <?php echo $eventMonth; ?></div>
<?php
// while ($row = $db->fetch_Array($sql_query)) {
foreach($rows as $row) {
?><p id="d<?php echo $row['id']; ?>"><b><?php echo $row['title']; ?></b><button>Edit</button><button>Delete</button></p>
<?php
}
?>
</div>
<br />
<div id="ajReturn" style="background: #cfc; border:2px solid #00d; min-height:2em;">No Return</div>
</body></html>

Open in new window


I do NOT add any value to the buttons, as they already have the Edit and Delete in their HTML, I do NOT duplicate data, and just place the database ID in the parent <p> element, so in JS you can get it with -
     $(this).parent().attr("id")

to make the ID with in the standards, I add a letter to the beginning a "d" -
    <p id="d<?php echo $row['id']; ?>">


Next is my   postie.php    code , for the non database ajax return string
<?php ini_set("display_errors",1); error_reporting(E_ALL);
$opp = empty($_POST['opp']) ? false : $_POST['opp'] ;
$id = empty($_POST['id']) ? false : $_POST['id'];

// do not do much in this except return a string to say information;
if(!$opp || !$id) {
  echo 'Server Data Error: SE-pst111';
// it may not be wise to have to much error info display to code oponents, 
// I use error lookup numbers like SE-op142
  exit;
  }

// YOU must do a CHECK of all POST data from out there (cound be hack input)
// these are not very good post text checks. but a place to start
if ((strlen($opp) < 4) || (strlen($opp) > 6)) {
  echo 'Server Data Error: SE-op142';
  exit;
  }

if (!is_numeric($id)) {
  echo 'Server Data Error: SE-i322';
  exit;
  }
// I can not do any Database so I return a string
if ($opp == 'Edit') {
  echo '<span style="color: #090; font-size:112%">Server Opperation Of EDIT (update) was done on the DataBase ID row '.$id.'</span>';
  } elseif ($opp == 'Delete') {
  echo '<span style="color: #900; font-size:112%">Server Opperation Of DELETE was done on the DataBase ID row '.$id.'</span>';  
  } else {
  echo 'Server Data Error: SE-op210 - '.$opp;  
  }
?>

Open in new window



I have included some info comments to explain some.
This works for me on a PHP ver 5.5 server, in firefox and chrome
Most Valuable Expert 2017
Distinguished Expert 2018
Commented:
AJAX is required to list the events of the day the user chooses from the calendar, generating rows with a hidden ID, a submit button named edit and a submit button named delete for the day chosen.  At that stage AJAX is no longer required.
Ok understood - we have been going down the wrong path - the Edit and Delete are simple form posts - hence your multiple forms that you created.

Consider this code
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>EE 2</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>
  <form action="t1280.php" method="post">
    <table id="events_table" class="table-striped">
      <tr>
        <td>First title</td>
        <td><button data-action="edit" name="edit" value="14">Edit</button></td>
        <td><button data-action="delete" name="delete" value="14">Delete</button></td>
      </tr>
      <tr>
        <td>Second title</td>
        <td><button data-action="edit" name="edit" value="27">Edit</button></td>
        <td><button data-action="delete" name="delete" value="27">Delete</button></td>
      </tr>
      <tr>
        <td>Third title</td>
        <td><button data-action="edit" name="edit" value="98">Edit</button></td>
        <td><button data-action="delete" name="delete" value="98">Delete</button></td>
      </tr>
    </table>
  </form> 
</body>
</html>

Open in new window

Note with the above
a) We wrapped the table in a single form
b) Each button has a name that is edit for edit buttons and delete for delete buttons
c) When you post the form the $_POST array holds the key value pair of button name : button value

In other words if you click an edit button $_POST looks like this
Array
(
    [edit] => 14
)

Open in new window

if you click a delete button your $_POST looks like this
Array
(
    [delete] => 14
)

Open in new window

You can now test for these conditions of
if (isset($_POST['edit'])) {
   // DO EDIT HERE WITH id = $_POST['edit']
}
else if (isset($_POST['delete'])) {
   // DO EDIT HERE WITH id = $_POST['delete']
}

Open in new window

PHP source for sample
<!doctype html>
<html>
<head>
</head>
<body>
<?php
if (isset($_POST['edit'])) {
   // DO EDIT HERE WITH id = $_POST['edit']
   $id = (int)$_POST['edit'];
   echo "Editing {$id}<br/>";
}
else if (isset($_POST['delete'])) {
   // DO DELETE HERE WITH id = $_POST['delete']
   $id = (int)$_POST['delete'];
   echo "Deleting {$id}<br/>";
}
?>
	<a href="t1280.html">Back to form</a>
</body>
</html>

Open in new window

You can see the code working here
???
 ? ? ? ? ?
colinspurs, the last code you have is using your version of AJAX with -
   function showEvent(str) {

this is a simplified JS Ajax run of code, the URL standards for GET pairs or POST pairs, require the encodeURIComponent( ) for any punctuation and or web addy non allowed text characters .

I can post some working code for the raw javascript ajax, but it takes some time to learn how and why AJax works, and what you can do and not do.

Although Jquery ajax is also a task to learn, many of the things, like use encodeURIComponent( )  on URL pairs is done for you.
Julian, I am glad you seem to understand what this is for, I am leaving this thread, it's more than I can decipher.

Author

Commented:
AJAX is required to list the events of the day the user chooses from the calendar, generating rows with a hidden ID, a submit button named edit and a submit button named delete
Funny how I wrote down what I should have been coding!

Both solutions work, one with and one without AJAX, so I think both deserve points.

Apologies for the mislead, not sure how that happened..uh oh...wait a minute, my answer to the 2nd question in the first reply probably.

Thanks also to Ray for the advice and links.

Julian, could you please post your CSS for table-striped?  

Thanks again all, I do appreciate the effort and frustration.

Col

Author

Commented:
Fantastic, I learned a lot.

Cheers
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
You are welcome
Julian, could you please post your CSS for table-striped?  
That comes from bootstrap - my sample pages are all based on bootstrap so 99% of the styling comes from there.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial