How best to format radio button array and capture in $_POST - php

I'm really struggling with an RSVP form I'm trying to set-up and any help would be great!
I have this form so far http://adrianandemma.com/ which I am trying to get to send me a simple email once submitted.
The form has a 'Name' field and a radio button for 'Attending - Yes/No'.
I then have some JS whereby you can clone these fields to RSVP for more than one guest at a time.
The 'Name' fields are passing through fine as an array and coming through by email, as I can just set the name attribute of the input to name="name[]", but I'm having trouble with the radio buttons.
I can't leave the 'name' attribute the same for the cloned radio buttons, because if I do I can only select yes/no for one cloned row, as all the cloned radios have the same name, so I have added a bit of JS to try to amend the name of any cloned radios to 'coming[1], coming[2], etc'.
I can't quite get this to work though, as every time I submit the form the radio button values appear to come through blank.
Can anybody advise the best approach to setting up radio buttons as an array and to carry them through via $_POST and ultimately an email script?
Here's my HTML form:
<?php
if(#$_REQUEST['submit'] == '1') {
include('assets/forms/rsvp.php');
}
?>
<form action="?" method="post">
<?php if(#$errors) :?>
<p class="errors"><?php echo $errors; ?></p>
<?php endif; ?>
<input type="hidden" name="submit" value="1" />
<div class="form-row">
<div class="field-l">
<p>Name</p>
</div>
<div class="field-r">
<p>Attending?</p>
</div>
</div>
<div class="form-row guest">
<div class="field-l">
<input type="text" name="name[]" id="name" value="<?php echo htmlspecialchars(#$_REQUEST['name']); ?>" tabindex="1" />
</div>
<div class="field-r">
<input type="radio" name="coming" id="coming-yes" class="coming-yes" value="Yes"><label for="coming-yes">Yes</label><input type="radio" name="coming" id="coming-no" class="coming-no" value="No"><label for="coming-no">No</label>
</div>
</div>
<a class="addguest" href="#">Add further guest</a>
<div class="form-row">
<button type="submit" id="rsvp-submit" tabindex="2">Submit RSVP</button>
</div>
</form>
Hers My Form Process code:
<?php
$name = $_POST['name'];
$coming = $_POST['coming'];
$errors = "";
if(!#$_POST['name']) { $errors .= "Please enter your name.<br/>\n"; }
if(!#$_POST['coming']) { $errors .= "Please enter yes or no for attending.<br/>\n"; }
if(#$_POST['emailaddress'] != '') { $spam = '1'; }
if (!$errors && #$spam != '1')
{
$to = "xxx#example.com";
$subject = "Wedding RSVP";
$headers = "From: noreply#adrianandemma.com";
$body = "The following RSVP has been sent via the website.\n\n";
for($i=0; $i < count($_POST['name']); $i++) {
$body .= "
Name ".($i+1)." : " . $_POST['name'][$i] . "\n
Coming ".($i+1)." : " . $_POST['coming'][$i] ."\n\n";
}
$body .= "\n\nDate Received: " . date("j F Y, g:i a") . "\n";
mail($to,$subject,$body,$headers);
}
?>
Here's my JS:
$(document).ready(function() {
$('.addguest').on('click', function(e) {
e.preventDefault();
//
// get the current number of ele and increment it
//
var i = $('.guest').length + 1;
$('.guest').first().clone().find("input").attr('id', function(idx, attrVal) {
return attrVal + i; // change the id
});
$('.guest').first().clone().find("input[type=radio]").attr('id', function(idx, attrVal) {
return attrVal + i; // change the id
}).attr('name', function(idx, attrVal) {
return attrVal+'['+i+']'; // change the name
}).val('').end().find('label').attr('for', function(idx, attrVal) {
return attrVal + i; // change the for
}).end().insertBefore(this);
});
});
Here's an example of what I'm receiving by email currently, names come through fine, but radio values for 'Coming Yes/No" are all blank:
The following RSVP has been sent via the website.
Name 1 : John Doe
Coming 1 :
Name 2 : Ann Doe
Coming 2 :
Name 3 : Fred Doe
Coming 3 :
Date Received: 19 April 2017, 1:04 am

Honestly, my best guess is that in the original row, the names of your radio inputs are simply "coming", without the brackets. I think that because there are no brackets on that name, it is clobbering the other ones of the same name that should behave as an array. In other words, PHP is getting two conflicting types for an input of the same name, and taking the string over the array.
Hard to say without testing it directly, and the fact that the input is referenced as an array in your PHP form handler and doesn't throw an error would tend to suggest to me I'm not quite right, but it may be worth a try.
Here's the change to the HTML I would try:
<div class="field-l">
<input type="text" name="name[0]" id="name" value="<?php echo htmlspecialchars(#$_REQUEST['name']); ?>" tabindex="1" />
</div>
<div class="field-r">
<input type="radio" name="coming[0]" id="coming-yes" class="coming-yes" value="Yes">
<label for="coming-yes">Yes</label>
<input type="radio" name="coming[0]" id="coming-no" class="coming-no" value="No">
<label for="coming-no">No</label>
</div>
Notice I specifically marked the first row as row zero, as PHP uses zero-indexed arrays.
This would then require some changes to your javascript. I've found it was easier to create an actual template for your row HTML and use that than to try and clone the first row each time and reset all the inputs and adjust the names. The way this works is you define your template HTML inside a script tag with an ID and a type that is non-standard. The browser ignores it, but JavaScript can access it just like any other element and we can pull the content out with jQuery's html() method.
Here's what I've come up with (including a fix of your indexing):
<!-- A script with a non-standard type is ignored by the browser -->
<!-- We can reference it by ID in our JS though, and pull out the HTML -->
<script id="guest-row-template" type="text/template">
<div class="form-row guest">
<div class="field-l">
<input type="text" name="" id="name" class="name-ipt" />
</div>
<div class="field-r">
<input type="radio" name="" id="" class="coming-yes coming-yes-ipt" value="Yes" />
<label for="" class="coming-yes coming-yes-label">Yes</label>
<input type="radio" name="" id="" class="coming-no coming-no-ipt" value="No" />
<label for="" class="coming-no coming-no-label">No</label>
</div>
</div>
</script>
<script type="text/javascript">
$(document).ready(function() {
$('.addguest').on('click', function(e) {
e.preventDefault();
//Get the number of rows we have already - this is the index of the *next* row
//If we have 1 row, the first row's index is 0 and so our next row's index should be
//1, which is also our length, no need to increment
var i = $('.guest').length;
//Get HTML template content for a single row
var row = $('#guest-row-template').html();
//Update the name attribute of the name input
row.find('.name-ipt').attr('name', 'name[' + i + ']');
//Update the name and id attributes of the yes radio button
row.find('.coming-yes-ipt').attr('name', 'coming[' + i + ']');
row.find('.coming-yes-ipt').attr('id', 'coming-yes-' + i);
//Update the name and id attributes of the no radio button
row.find('.coming-no-ipt').attr('name', 'coming[' + i + ']');
row.find('.coming-no-ipt').attr('id', 'coming-no-' + i);
//Update the for attribute of the yes label
row.find('.coming-yes-label').attr('for', 'coming-yes-' + i);
//Update the for attribute of the no label
row.find('.coming-no-label').attr('for', 'coming-no-' + i);
row.insertBefore(this);
});
});
</script>
Please note this is untested code. Of course I've gone through a few times to make sure I caught all my obvious bugs, but others may persist. Since I can't actively test it, I can't say it's entirely bug free. But, hopefully as pseudo-code it helps you resolve the issue.
EDIT 1
Just to clarify, you don't ordinarily have to manually provide the index values within the brackets of input names for PHP to interpret the input as an array and to automatically index the input in the appropriate order. I specifically set the first inputs to have use [0] because all the inputs after them will also need to specify index values in order for your radio buttons to work (I personally appreciate consistency), and because we need to be absolutely sure that the correct names are matched to the correct RSVP value (just trying to be thorough).

Related

Form auto calculate answer to php

I have an autocalc running on a form and the total is shown through a div ID. I need to be able to somehow render the div ID answer into a php form mailer.
I’ve tried adding a hidden input field with the div ID.
<div id="totalPriceTM">
<input name="Score" id="totalPriceTM" value="" type="hidden" />
</div>
No error messages but result not showing in email.
You should create different div name on your form.
for example :
<script>
function autocalc(x,y)
{
a = x*y;
document.getElementById(totalPriceTM).innerHTML = a;
document.getElementById(totalPriceTM2).value = a;
}
</script>
<div id="totalPriceTM">
<input name="Score" id="totalPriceTM2" value="" type="hidden" />
</div>
result will be show on div totalPriceTM and will be set the value of div totalPriceTM2

Inserting values to the database with hidden fields and checkbox

Good day!
Im currently having problems with inserting values with checkbox and hidden field. Any tips or solutions are greatly appreciated.
So my problem is this: I have a form with only checkboxes in it and a submit button and If I check one of the values in a checkbox a hidden upload field will be displayed the hidden value must be connected to the chosen value in the checkbox. How can I insert the hidden value to the corresponding checkbox value in a database. For example
HTML:
<label class="form-check-label">
<input class="form-check-input" name="value[]" type="checkbox" value="Venue">
Value 1
<div id="hidden_fields">
This is hidden: <input type="text" id="hidden_one" name="hidden_one[]">
</div>
</label>
<br>
<label class="form-check-label">
<input class="form-check-input" name="value[]" type="checkbox" value="Venue">
Value 2
<div id="hidden_fields">
This is hidden: <input type="text" id="hidden_one" name="hidden_one[]">
</div>
</label>
<br>
PHP:(Updated) This is what I have now. when I dont check the 1st checkbox. the hidden_one in the 2nd checkbox isnt inserting
foreach($_POST['value'] as $key=>$value ){
$hidden_one = $_POST["hidden_one"][$key];
$sql = "INSERT INTO sample (value, hidden_one) VALUES ('$value','$hidden_one')";
$result = mysqli_query($connection, $sql);
}
If I check value 1 and entered a sample1 in the hidden form and I check value 2 and entered a sample2 in the hidden form. sample 1 must be in the same column as value 1 and sample 2 must be in the same column as value 2. its not inserting properly
UPDATE:
So I changed the code into this
foreach($_POST['value'] as $key=>$value ){
$hidden_one = $_POST["hidden_one"][$key];
but the problem is sometimes its not inserting correctly. Sometimes hidden_one is empty in the database. I'm really lost at the moment. Can't find a solution elsewhere.
This is my updated form
Im seeing a pattern, when I skipped a checkbox like I check value1 then skip value2 then check value3. value3 hidden isn't inserted. Still not solved :( lol this is driving me crazy. at the verge of quitting. lol
One way you could insert the value of your checkbox into your hidden input fields, is by making a click function that takes $(this).val(), which is your clicked elements value. You can then put that value into a variable. You then go to target the parent element/container for the targeted checkbox and find the corresponding input field. You then simply set the value of that input field with the declared value of the checkbox.
Note that the notation for this JavaScript is in jQuery, and you will need to include a jQuery library in order for this solution to work.
$(document).ready(function () {
$('[name="value[]"]').click(function(){
var mySelect=$(this).val();
if( $(this).prop('checked') ) {
$(this).parent().find('input[name="hidden_one[]"]').val(mySelect);
}
else {
$(this).parent().find('input[name="hidden_one[]"]').val("");
}
})
});
Example:
$(document).ready(function () {
$('[name="value[]"]').click(function(){
var mySelect=$(this).val();
if( $(this).prop('checked') ) {
$(this).parent().find('input[name="hidden_one[]"]').val(mySelect);
}
else {
$(this).parent().find('input[name="hidden_one[]"]').val("");
}
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class="form-check-label">
<input class="form-check-input" name="value[]" type="checkbox" value="Venue 1">
Value 1
<div id="hidden_fields">
This is hidden: <input type="text" id="hidden_one" name="hidden_one[]">
</div>
</label>
<br>
<label class="form-check-label">
<input class="form-check-input" name="value[]" type="checkbox" value="Venue 2">
Value 2
<div id="hidden_fields">
This is hidden: <input type="text" id="hidden_one" name="hidden_one[]">
</div>
</label>
<br>
Direct JS Fiddle link
When it comes to inserting the value(s) into the database, it's hard for me to give a concise answer, because I don't have any debugging information on your application, so I don't know if you have structered it properly. I would assume you have either an AJAX function or a form action to post your values. As you noted in your own attempt, is that the values come up as an array that you will have to loop through. However, I am uncertain of the nested foreach loops.
Let me know if you need any further assistance, and in that case, update your question with potential error messages, corresponding form/ajax code, and if your PHP file holds any other relevant information, add that too.
A rough example could be:
<?php
$hidden_one_array=array_values($_POST['hidden_one']); //our posted array
$i=0; // iterator
$length=count($hidden_one_array); //length of the array
while($i < $length) {
$sql="INSERT INTO sample (value, hidden_one) VALUES ('$value','$hidden_one_array[$i]')";
$result=mysqli_query($connection, $sql);
$i++;
}
?>
What we're doing here is basically looping through the array, using the iterator value as our index pointer to each respective array index to insert into the database.
Also note that you should probably look into prepared statements to prevent sql injection. You are already using mysqli_ so might as well take advantage of it.

PHP POST values from selected textboxes

I'm trying to create a comparison page/form using a combination of PHP, HTML and jQuery. The ideal effect I like to create as below
<form>
left | right
[text1.l] | [text1.r]
[text2.l] | [text2.r]
submit
</form>
Where [] denotes an input text box. For a particular use case, the user select would select either the left or right textbox for each row and post the form. Essentially I am only interested in the value of the text box selected when I process the form.
I was thinking of perhaps using a radio button as I only allow selection of one box per row, but I am unsure how set this up to retrieve the text box value.
Any helps would be appreciated, cheers.
JSFIDDLE http://jsfiddle.net/Bq8AF/
Form
<form method="post" action="process.php" class="form">
<fieldset id="left">Left
<input type="text" name="foo-left-1" size="50" />
<input type="text" name="foo-left-2" size="50" />
</fieldset>
<fieldset id="right">Right
<input type="text" name="foo-right-1" size="50" />
<input type="text" name="foo-right-2" size="50" />
</fieldset>
<input type="submit" value="Submit">
</form>
JS + jQuery
$("input[type=text], textarea").focus(function(){
// Check for the change from default value
if(this.value == this.defaultValue){
this.select();
}
// get the name of the field, e.g. foo-left-1
//alert(this.name);
var fieldNameSplitted = this.name.split("-");
// recombine + switch "left" to "right" and vice versa
var fieldNameOtherSide = '';
// the ident remains the same (e.g. foo-)
var fieldNameOtherSide = fieldNameSplitted[0] + "-";
// left/right switch (e.g. foo-left, gets foo-right and vv)
if(fieldNameSplitted[1] == 'left') { fieldNameOtherSide += 'right-'; }
if(fieldNameSplitted[1] == 'right') { fieldNameOtherSide += 'left-'; }
// row number (e.g. foo-right-2)
fieldNameOtherSide += fieldNameSplitted[2];
// now we have the name of the field on the other side of the row, right?
//alert(fieldNameOtherSide);
// use that as jQuery selector and disable the element
// because the user has selected the other one
// and when the form is send disabled fields will not be send
// http://www.w3.org/TR/html401/interact/forms.html#disabled
$('input[name=' + fieldNameOtherSide + ']').prop("disabled", true);
});
The user selects the textbox by click.
When "submit" is clicked, a browser will only send the not-disabled fields.
The $_POST array will only contain the values from all not-disabled fields.
When a user enters this:
you would get $_POST['foo-right-1'] = 'car' and $_POST['foo-left-2'] = 'dog'.

PHP AJAX within a table

I have a table that lists my students.. and the License Number Column will either shown the license number or if there is no number in the DB it will show a textbox..
Upon submit (note: no submit button, to keep it need i just press return)
The results from the PHP script will be shown via Ajax.
My complete code is here.
http://pastebin.com/9k0EKXA9
Here is the code within the license number cell on each row:
<td><?php // check if license number exists.
if($row['license_no'] == '')
{
//show form.
?>
<form method="POST" id="license_no_update"">
<input type="text" name="license_no" value="License Number" />
<input type="hidden" value="<?php echo $row['student_id']; ?>" name="student_id" />
</form>
<div id="output"></div>
<?php
}else{
//show license no.
echo $row['license_no'];
}
?></td>
Here Is the JQUERY
<script type="text/javascript">
$(document).ready(function() {
$("#license_no_update").submit(function() {
var license_no_update = $(this).serialize();
$.post('license_update.php', license_no_update, function(data) {
// We not pop the output inside the #output DIV.
$("#output").html(data);
});
return false;
});
});
</script>
The problem i am having, even after searching google many times..
I know i have to have a new form & element id for each row of the table.
but even when i do have those, i do not know how to get JQUERY to find that unique number..
currently with the code attached if i submit on the first row of the table, the correct results are displayed, if i submit on any other row nothing is displayed..
I hope that all makes sense.
Regards
Aaron
Use .find() to find the value of the hidden input within the clicked form. Notice the use of $(this) which is the form itself, and then you can narrow down the input by it's name, since you know the name.
However, it is unclear what you want to do with the id so I left that up to you.
$("#license_no_update").submit(function() {
var studentID = $(this).find("input[name='student_id']").val();
var license_no_update = $(this).serialize();
$.post('license_update.php', license_no_update, function(data) {
// We not pop the output inside the #output DIV.
$("#output-" + studentID).html(data);
});
return false;
});
Update:
Here is one way of creating unique ID's for each output:
if($row['license_no'] == '')
{
//show form.
?>
<form method="POST" id="license_no_update"">
<input type="text" name="license_no" value="License Number" />
<input type="hidden" value="<?php echo $row['student_id']; ?>" name="student_id" />
</form>
<div id="output-<?php echo $row['student_id']; ?>"></div>
<?php
}else{
//show license no.
echo $row['license_no'];
}

Dynamically added input fields not getting posted?

The code below consists of invoice-lines that contain some input fields that the user can fill out. The initial number of input lines is 20. Users will often need to add more lines to the invoice by clicking the "Add lines" button. Every click of this button uses Javascript to append more lines to the invoice.
The problem is when the form gets submitted only the first 20 lines seem to get submitted. All the javascript appended invoice lines are ignored and never POSTed.
I have been trying to work out this problem for quite a while now, I was wondering if someone can guide me as to how to go about implementing this correctly?
Many thanks in advance.
Markup / PHP
<?php
for($i=0; $i < 20; $i++){
echo '
<div class="invoice-line">
<div class="prod-id-cell"><input name="rows['.$i.'][id]" type="text" class="prod-id-input">
<div class="smart-suggestions">
<!-- RESULT SUGGESTIONS WILL POPULATE HERE --> </div>
</div>
<div class="prod-name-cell">
<input type="text" name="rows['.$i.'][name]" class="prod-name-input"/> <div class="smart-suggestions">
<!-- RESULT SUGGESTIONS WILL POPULATE HERE -->
</div>
</div>
<div class="price-cell"><input name="rows['.$i.'][price]" class="price-input" type="text" /></div>
<div class="quantity-cell"><input name="rows['.$i.'][quantity]" type="text" class="quantity-input"></div>
<div class="unit-price-cell"><input name="rows['.$i.'][unit-price]" class="unit-price-input" type="text" /></div>
<div class="num-kits-cell"><input name="rows['.$i.'][num-kits]" class="num-kits-input" type="text" /></div>
<div class="amount-cell"><input name="rows['.$i.'][amount]" class="amount-input" type="text" readonly="readonly" /></div>
</div>';
}
?>
Javascript
//**ADD 5 LINES**//
$('.invoice-links div').on("click", ".add-five-trigger", function(){
for(var i=0; i < 5; i++){
var invoiceLine = $(".invoice-line").first().clone( true, true );
$(invoiceLine).insertAfter(".invoice-line:last");
$(".invoice-line:last").find('input').val('').attr('disabled','disabled');
}
});
You forgot to change the name attributes of the cloned inputs. They would overwrite previous fields.
Use this:
var invoiceLine = $(".invoice-line").last();
var newLine = invoiceLine.clone( true, true );
invoiceLine.after(newLine);
newLine.find('input').each(function() {
if (this.type == "text")
this.value = "";
this.name = this.name.replace(/rows\[(\d+)\]/, function(m, num) {
return "rows["+(+num+1)+"]";
});
this.disabled = true;
});
The values are not being posted because you are disabling them. Input elements with disabled attribute don't get posted.
Also, always make sure that elements have unique ids and names. Elements without names don't get posted.
You are not giving new names to the elements you create. You are also disabling them.
$(".invoice-line:last").find('input').val('').attr('disabled','disabled');
Disabled form inputs will never be submitted with the form.

Categories