Jump to content

Creating array to POST with jQuery


Go to solution Solved by Barand,

Recommended Posts

Hi All,

I have a form that allows the user to provide data in input boxes)

I have a button that allows the user to add more rows (the same as row 1 repeated)

I am using Ajax to post this form but my question is, how do i build the array in jquery of all of the inputs that will then be posted to PHP to insert into the database.

The form looks like this:

<div class="row mb-3 zone-row">
  <div class="col">
    <label for="zoneType" class="form-label">Zone Type</label>
    <select id="zoneType" class="form-select zoneType">
      <option value="1">Normal Zone</option><option value="2">Special Zone</option>							
    </select>
  </div>
  <div class="col">
    <label for="zoneName" class="form-label">Zone Name</label>
    <input type="text" class="form-control simple-string zoneName" id="zoneName">
  </div>
  <div class="col">
    <label for="printValue" class="form-label">Print Value</label>
    <input type="text" class="form-control simple-string printValue" id="printValue">
  </div>
</div>

when clicking the button to add another row - it adds:

<div class="row mb-3 extra-row">
  <div class="col">
    <select id="" class="form-select zoneType"> 
      <option value="1">Normal Zone</option>
      <option value="2">Special Zone</option> 
    </select>
  </div>
  <div class="col">
    <input type="text" class="form-control simple-string zoneName" id="">
  </div>
  <div class="col">
    <input type="text" class="form-control simple-string printValue" id="">
  </div>
</div>

i expect that this will need to be some sort of each function?

Link to comment
https://forums.phpfreaks.com/topic/318328-creating-array-to-post-with-jquery/
Share on other sites

I seem to be collecting the data with the following

$('#addZonesButton').on('click', function() {
			$zTypes = $('.zoneType').each(function() {
				$zType = $(this).val()
				console.log($zType);
			})
		})

but how would i then create the array needed in order to post it

I am not sure if this is getting me closer or further away.

$('#addZonesButton').on('click', function() {
  $zNameArr = []
  $zPrintArr = []
  $('.zoneType').each(function() {
    $zType = $(this).val()

  })
  $('.zoneName').each(function() {
    $zName = $(this).val()
    $zNameArr.push($zName)
  })
  $('.printValue').each(function() {
    $pVal = $(this).val()
    $zPrintArr.push($pVal)
  })
		})

 

Landed here:

Seems to be working but i dont know if there is a more optimal way of doing this.  Feels a bit like a hack.

$('#addZonesButton').on('click', function() {
			$zNameArr = []
			$zPrintArr = []
			$zTypeArr = []
			$data = [];
			$('.zoneType').each(function() {
				$zType = $(this).val()
				$zTypeArr.push($zType)

			})
			$('.zoneName').each(function() {
				$zName = $(this).val()
				$zNameArr.push($zName)
			})
			$('.printValue').each(function() {
				$pVal = $(this).val()
				$zPrintArr.push($pVal)
			})

			for (i = 0; i < $zNameArr.length; i++) {

				$data[i] = Array($zTypeArr[i], $zNameArr[i], $zPrintArr[i]);
			}
	
			$filteredData = $data.filter(function(x) {
				/* here, x is an array, not an object */
				return !(x.some(element => element === (undefined || null || '')))
			});
			
		})

The data is output as:

 

[
  [
    "1",
    "1",
    "p1"
  ],
  [
    "1",
    "3",
    "p3"
  ],
  [
    "1",
    "2",
    "p2"
  ]
]

Would have preferred this to have keys also.

Now i need to send it to php with ajax and insert it.

Edited by Adamhumbug

if you put the form fields inside a form, and give them array names, you can use the jquery .serialize() method to get the form data using a single line of code - https://api.jquery.com/serialize/ you would use this in the data value in the .ajax call, e.g. data: $(this).serialize(),

next, if you put the dynamically to-be added markup inside a <template></template> tag, it is simple to dynamically add it - https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template

if you put the closing </label> tag after the form field it corresponds to, you can leave out the for='...' attributes and the corresponding id='...' attributes, and make the labels work for the dynamically added fields.

Here's a sample script

<?php

##
##  HANDLE AJAX REQUEST
##
    if (isset($_POST['ajax']))   {
        if ($_POST['ajax']=='testdata') {
            exit('<pre>' . print_r($_POST, 1) . '</pre>');      // JUST RETURNS THE ARRAY OF POSTED DATA FOR DISPLAY
        }
        exit();
    }
    
?>
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="utf-8">
   <title>Example</title>
   <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
   
   <script type='text/javascript'>
       $(function() {
           $("#form1").submit(function(ev) {
               ev.preventDefault()
               let fdata = $(this).serialize()
               console.log(fdata)
               $.post(
                   "",
                   fdata,
                   function(resp) {
                       $("#test-output").html(resp)
                   },
                   'TEXT'
               )
           })
       })
   </script> 
</head>
<body>
    <form id='form1'>
    <input type='hidden' name='ajax' value='testdata'>
      <div class="col">
        <label for="zoneType" class="form-label">Zone Type</label>
        <select name="zoneType[]" class="form-select zoneType">
          <option value="1">Normal Zone</option><option value="2">Special Zone</option>                            
        </select>
      </div>
      <div class="col">
        <label for="zoneName" class="form-label">Zone Name</label>
        <input type="text" class="form-control simple-string zoneName" name="zoneName[]">
      </div>
      <div class="col">
        <label for="printValue" class="form-label">Print Value</label>
        <input type="text" class="form-control simple-string printValue" name="printValue[]">
      </div>
      <br>
      
      <div class="col">
        <label for="zoneType" class="form-label">Zone Type</label>
        <select name="zoneType[]" class="form-select zoneType">
          <option value="1">Normal Zone</option><option value="2">Special Zone</option>                            
        </select>
      </div>
      <div class="col">
        <label for="zoneName" class="form-label">Zone Name</label>
        <input type="text" class="form-control simple-string zoneName" name="zoneName[]">
      </div>
      <div class="col">
        <label for="printValue" class="form-label">Print Value</label>
        <input type="text" class="form-control simple-string printValue" name="printValue[]">
      </div>
      <br>
      
      <div class="col">
        <label for="zoneType" class="form-label">Zone Type</label>
        <select name="zoneType[]" class="form-select zoneType">
          <option value="1">Normal Zone</option><option value="2">Special Zone</option>                            
        </select>
      </div>
      <div class="col">
        <label for="zoneName" class="form-label">Zone Name</label>
        <input type="text" class="form-control simple-string zoneName" name="zoneName[]">
      </div>
      <div class="col">
        <label for="printValue" class="form-label">Print Value</label>
        <input type="text" class="form-control simple-string printValue" name="printValue[]">
      </div>
      <br>
    <input type='submit'>
    </form>
    <div id='test-output'>
    </div>
</body>
</html>

[edit]...

NOTE - your form's input fields need name attributes

46 minutes ago, Barand said:

Here's a sample script

<?php

##
##  HANDLE AJAX REQUEST
##
    if (isset($_POST['ajax']))   {
        if ($_POST['ajax']=='testdata') {
            exit('<pre>' . print_r($_POST, 1) . '</pre>');      // JUST RETURNS THE ARRAY OF POSTED DATA FOR DISPLAY
        }
        exit();
    }
    
?>
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="utf-8">
   <title>Example</title>
   <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
   
   <script type='text/javascript'>
       $(function() {
           $("#form1").submit(function(ev) {
               ev.preventDefault()
               let fdata = $(this).serialize()
               console.log(fdata)
               $.post(
                   "",
                   fdata,
                   function(resp) {
                       $("#test-output").html(resp)
                   },
                   'TEXT'
               )
           })
       })
   </script> 
</head>
<body>
    <form id='form1'>
    <input type='hidden' name='ajax' value='testdata'>
      <div class="col">
        <label for="zoneType" class="form-label">Zone Type</label>
        <select name="zoneType[]" class="form-select zoneType">
          <option value="1">Normal Zone</option><option value="2">Special Zone</option>                            
        </select>
      </div>
      <div class="col">
        <label for="zoneName" class="form-label">Zone Name</label>
        <input type="text" class="form-control simple-string zoneName" name="zoneName[]">
      </div>
      <div class="col">
        <label for="printValue" class="form-label">Print Value</label>
        <input type="text" class="form-control simple-string printValue" name="printValue[]">
      </div>
      <br>
      
      <div class="col">
        <label for="zoneType" class="form-label">Zone Type</label>
        <select name="zoneType[]" class="form-select zoneType">
          <option value="1">Normal Zone</option><option value="2">Special Zone</option>                            
        </select>
      </div>
      <div class="col">
        <label for="zoneName" class="form-label">Zone Name</label>
        <input type="text" class="form-control simple-string zoneName" name="zoneName[]">
      </div>
      <div class="col">
        <label for="printValue" class="form-label">Print Value</label>
        <input type="text" class="form-control simple-string printValue" name="printValue[]">
      </div>
      <br>
      
      <div class="col">
        <label for="zoneType" class="form-label">Zone Type</label>
        <select name="zoneType[]" class="form-select zoneType">
          <option value="1">Normal Zone</option><option value="2">Special Zone</option>                            
        </select>
      </div>
      <div class="col">
        <label for="zoneName" class="form-label">Zone Name</label>
        <input type="text" class="form-control simple-string zoneName" name="zoneName[]">
      </div>
      <div class="col">
        <label for="printValue" class="form-label">Print Value</label>
        <input type="text" class="form-control simple-string printValue" name="printValue[]">
      </div>
      <br>
    <input type='submit'>
    </form>
    <div id='test-output'>
    </div>
</body>
</html>

[edit]...

NOTE - your form's input fields need name attributes

Amazing, i have modified your code a little so that it fits with how i have done everything else (and i can understand it in the future)

		$("#newZones").submit(function(ev) {
			ev.preventDefault()
			let fdata = $(this).serialize()
			console.log(fdata)
			$.ajax({
				type: 'post',
				data: {
					'ajax': 'addNewZones',
					'data': fdata,

				},
				success: function(resp) {
					$('.alert-container').html(resp).show()
				}
			})
		})

and

if (isset($_POST['ajax'])) {
	switch ($_POST['ajax']) {
		case 'addNewZones':
			exit(addNewZones($pdo, $_POST['data']));
			break;
	}
}

Once the data has been sent into PHP function. Do i need to unserialise it to insert it?

Also, if the zone name field is blank the whole row of 3 fields need to be removed from the array that is sent.  Would this be a filter?

 

Edited by Adamhumbug
58 minutes ago, mac_gyver said:

if you put the form fields inside a form, and give them array names, you can use the jquery .serialize() method to get the form data using a single line of code - https://api.jquery.com/serialize/ you would use this in the data value in the .ajax call, e.g. data: $(this).serialize(),

next, if you put the dynamically to-be added markup inside a <template></template> tag, it is simple to dynamically add it - https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template

if you put the closing </label> tag after the form field it corresponds to, you can leave out the for='...' attributes and the corresponding id='...' attributes, and make the labels work for the dynamically added fields.

Thanks for this.  I will certainly have a look at <template> and great tip on the lables.

This seems to suggest that i have got it how i need it - i think

 

function addNewZones($pdo, $zoneArr)
{
	$params = array();
	parse_str($zoneArr, $params);
	echo ("<pre>");
	var_dump($params);
	echo "</pre>";
}
array(3) {
  ["zoneType"]=>
  array(3) {
    [0]=>
    string(1) "1"
    [1]=>
    string(1) "1"
    [2]=>
    string(1) "1"
  }
  ["zoneName"]=>
  array(3) {
    [0]=>
    string(1) "1"
    [1]=>
    string(1) "3"
    [2]=>
    string(1) "5"
  }
  ["printValue"]=>
  array(3) {
    [0]=>
    string(1) "2"
    [1]=>
    string(1) "4"
    [2]=>
    string(1) "6"
  }
}

 

Edited by Adamhumbug

Your POST array looks like this, as you separate the "ajax" value from the serialized data in your JSON string...

Array
(
    [ajax] => testdata
    [data] => zoneType%5B%5D=1&zoneName%5B%5D=aa&printValue%5B%5D=1&zoneType%5B%5D=1&zoneName%5B%5D=bb&printValue%5B%5D=2&zoneType%5B%5D=1&zoneName%5B%5D=cc&printValue%5B%5D=3
)

 

With my code, where only the serialized form data is sent (which includes the "ajax" value from a hidden form field) it looks like this...

Array
(
    [ajax] => testdata
    [zoneType] => Array
        (
            [0] => 1
            [1] => 1
            [2] => 1
        )

    [zoneName] => Array
        (
            [0] => aa
            [1] => bb
            [2] => cc
        )

    [printValue] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )

)

 

1 hour ago, Barand said:

Your POST array looks like this, as you separate the "ajax" value from the serialized data in your JSON string...

Array
(
    [ajax] => testdata
    [data] => zoneType%5B%5D=1&zoneName%5B%5D=aa&printValue%5B%5D=1&zoneType%5B%5D=1&zoneName%5B%5D=bb&printValue%5B%5D=2&zoneType%5B%5D=1&zoneName%5B%5D=cc&printValue%5B%5D=3
)

 

With my code, where only the serialized form data is sent (which includes the "ajax" value from a hidden form field) it looks like this...

Array
(
    [ajax] => testdata
    [zoneType] => Array
        (
            [0] => 1
            [1] => 1
            [2] => 1
        )

    [zoneName] => Array
        (
            [0] => aa
            [1] => bb
            [2] => cc
        )

    [printValue] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )

)

 

is that becuase my code is "wrong" - should i be switching to your way that works or is there another way around.

$("#newZones").submit(function(ev) {
			ev.preventDefault()
			let fdata = $(this).serialize() + "&ajax=addNewZones";



			$.ajax({
				type: 'post',
				data: fdata,
				success: function(resp) {
					console.log(resp);
					$('.alert-container').html(resp).show()
					// if (resp == "User Created") {
					// 	$(':input', '#createNewUser')
					// 		.not(':button, :submit, :reset, :hidden')
					// 		.val('')
					// 		.prop('checked', false)
					// 		.prop('selected', false);
					// }
				}
			})
		})

 

function addNewZones($pdo)
{
	$sql = "INSERT INTO zones (name, print_value, event_site_attachment_id, zone_type_attachment_id) values (:name, :printVal, :siteId, :zTypeId)";
	$stmt = $pdo->prepare($sql);
	echo "<pre>";
	var_dump($_POST);
	echo "</pre>";
}

This is now showing what looks like the right output

array(4) {
  ["zoneType"]=>
  array(2) {
    [0]=>
    string(1) "1"
    [1]=>
    string(1) "1"
  }
  ["zoneName"]=>
  array(2) {
    [0]=>
    string(1) "1"
    [1]=>
    string(1) "3"
  }
  ["printValue"]=>
  array(2) {
    [0]=>
    string(1) "2"
    [1]=>
    string(1) "4"
  }
  ["ajax"]=>
  string(11) "addNewZones"
}

How does one go about looping through this array to insert it into the DB but only when a zone name is present.

  • Solution
6 minutes ago, Adamhumbug said:
		let fdata = $(this).serialize() + "&ajax=addNewZones";

Yes.

That is what I was going to suggest if you didn't want to use the hidden field approach. That way you send just a single querystring which will be handled automatically to create the $_POST array

12 minutes ago, Adamhumbug said:

How does one go about looping through this array to insert it into the DB but only when a zone name is present.

Perhaps

    $stmt = $pdo->prepare("INSERT INTO mytable (zoneType, zoneName, printValue) VALUES (?,?,?)");
    foreach ($_POST['zoneName'] as $k => $zn)  {
        if ($zn) {
            $stmt->execute([ $_POST['zoneType'][$k], $zn, $_POST['printValue'][$k] ]);
        }
    }

 

  • Great Answer 1
4 minutes ago, Barand said:

Yes.

That is what I was going to suggest if you didn't want to use the hidden field approach. That way you send just a single querystring which will be handled automatically to create the $_POST array

Perhaps

    $stmt = $pdo->prepare("INSERT INTO mytable (zoneType, zoneName, printValue) VALUES (?,?,?)");
    foreach ($_POST['zoneName'] as $k => $zn)  {
        if ($zn) {
            $stmt->execute([ $_POST['zoneType'][$k], $zn, $_POST['printValue'][$k] ]);
        }
    }

 

You are a wonderful human.

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.