PHP Form: One to many UI relationships, represented in Javascript/jQuery? - javascript

I have a simple problem, but for some reason cannot figure out the words to find a solution (or which I'm sure there are many). I'm building a simple PHP form for a user, who may have zero-to-infinite phone numbers and one-to-infinite email-addresses.
I want one PHP page which allows me to click a button like "add new phone number" and another phone number field pops up. Next to each field should be a delete icon which removes that row. When I submit the form I want to be able to process it in PHP, ideally in a simple way.
The problem is I'm manually writing out the jQuery line-by-line and trying to build a framework to make it so I can easily apply this to other fields. Then I realized it must have been done already, and I'm reinventing the wheel.
Does anyone know of any simple one-to-many tools to spare me reinventing the wheel?
UPDATE Turns out I should have been searching for "form element repeater" or "form input cloning" or some similar phrase, instead of "jquery one to many inputs". The new phrases yielded the results found in my accepted (my own) answer.

Two frameworks:
SheepIt: http://www.mdelrosso.com/sheepit/index.php?lng=en_GB&sec=home
jQuery Form Element Repeater Plugin: https://github.com/cballou/jQuery-Form-Element-Repeater-Plugin

$('.add-input').click(function(){
var num = $(this).attr('data-num'),
$newInput = $('<input data-input="' + num + '" type="tel"/>'),
$delete = $('<a class='delete'/>');
$delete.on('click', function(ev){
$newInput.remove();
});
$('#formName').append($newInput + $delete);
}) ;
Something along the lines of this should work fine. It generates a input and delete button attaching a click event to the delete button generated and uses data attributes so you can keep track of inputs through PHP.

Your html code should look like this <input name="phonenumber[]">
Your jquery code will look like this
$('#add_phonenumber').click(function(){
$('#my_form').append('<input name="phonenumber[]">'); //add
});
$('.delete_me').click(function(){
$(this).closest('span or div').find('input').remove(); // delete (NOTE: your delete button and an input must be in one container for each input)
});
<span class="inputs"><input type="text" name="phonenumber[]"><a class="delete_me">delete this input</a></span>
Your php form handler
$new = array();
$phones = $_POST['phonenumber'];
$count = count( $phones );
for ( $i = 0; $i < $count; $i++ ) {
if ( $phones[$i] != '' ) :
$new[$i]['phonenumber'] = stripslashes( strip_tags( $phones[$i] ) );
endif;
}
// now array $new contains your phone numbers, you can save it or whatever you want to do with it

As a simple alternative maybe you could have one input box and separate the multiple entries with semi-colons or some other marker. Then in the php script you could use the explode function to separate them out into an array. e.g. :
johndoe#gahoo.com; janedoe#gahoo.com;jamesdoe#gahoo.com;
This would allow cut and paste of e.g. strings of email addresses, so for some applications it might be a preferable solution, as well as requiring minimal coding

Related

JQuery & PHP - How to save reordered group of divs within a form?

I know there are similar questions out there, but I can't seem to find one that answers my particular problem. I have a form that contains a group of divs that are generated based on a JSON array (that is saved in a separate JSON file).
I'm using Bootstrap for the design foundation (I'll spare you the lengthy HTML markups) & the "sortable" function of JQueryUI to reorder the list. The problem I can't seem to solve is how to save that order when I update the JSON.
This is my current setup:
<script>
var wrapper=$('#eventWrapper');
$(wrapper).sortable();
$(wrapper).disableSelection();
var add_button=$('#addEventButton');
$.getJSON('events.json',function(events){
var count=Object.keys(events).length;
if(count>0){
for(var i=1;i<=count;i++){
//Load the input values
var name=events[i].name;
var date=events[i].date;
//Build the event card
var currentEvent='<div class="ui-state-default">...<input type="text" name="event'+i+'[name]" value="'+name+'">...<input type="text" name="event'+i+'[date]" value="'+date+'">...<button class="remove_event">Remove event</button></div>';
//Newest event on top, plz!
$(wrapper).prepend(currentEvent);
}
};
var x=count;
$(add_button).click(function(e){
e.preventDefault();
x++;
var newEvent='<div class="ui-state-default">...<input type="text" name="event'+x+'[name]">...<input type="text" name="event'+x+'[date]">...<button class="remove_event">Remove event</button></div>';
$(wrapper).prepend(newEvent);
});
$(wrapper).on("click",".remove_event",function(e){
e.preventDefault();
$(this).parent('div').remove();
x--;
});
});
$('#updateBtn').click(function(e){
e.preventDefault();
$.ajax({
type:'POST',
url:'updateList.php',
data:$('#eventForm').serialize(),
success:...
});
});
And for the updateList.php:
<?php
$json=json_encode($_POST);
$file='events.json';
file_put_contents($file, $json);
if(file_exists($file)){
echo json_encode(array('success'=>1));
}else{
echo json_encode(array('success'=>0));
}
?>
The #eventForm encapsulates the series of events first built by the JSON then added/deleted/reordered by the user (click/drag using sortable(), remove button, and add event button). How would I update the x value of the input array to reflect the reordered list before or when the form is submitted?
Looks like I solved my own problem! Here's what I did if anyone else comes across a similar problem in their project:
I changed this bit of code:
for(var i=1;i<=count;i++){
//Load the input values
var name=events[i].name;
var date=events[i].date;
to this:
for(i in events){
var name=events[i].name;
var date=events[i].date;
Simple change in the "for" loop makes a world of difference!
I wasn't saving incorrectly, but rather reading the content from the JSON file incorrectly. If the user reorders the cards [1,2,3,4] as [3,2,4,1], I previously read the JSON file as [3,2,4,1] based on the given input "names".
Now on reload, the old [3,2,4,1] is now read sequentially as [1,2,3,4], ignoring whatever the input "names" may be.

New Text field when Button is clicked

I have a problem that hopefully someone can help me with. I have a webpage I've been building with html and php that has text fields that you fill out and submit to create an evaluation. What I would like to do is be able to click the Add Another Criteria button to add another criteria name and description field to the page and the Add criteria and create buttons would then go below the newest set of text fields created.
All this information is going to be stored in a database using PHP controller files so I am not sure if using Javascript would be the best way to achieve my goal. I apologize for my lack of php knowledge I am very new to this any help would be much appreciated Thank you!
This would be easier if you're using jQuery, but without, it's still possible.
var newCriteria = document.createElement("input");
newCriteria.setAttribute('placeholder', 'Criteria Name');
newCriteria.name = 'criteria[]';
var newDesc = document.createElement("textarea");
newDesc.setAttribute('placeholder', 'Description');
newDesc.name = 'description[]';
document.getElementById("theForm").appendChild(newCriteria);
document.getElementById("theForm").appendChild(newDesc);
On the PHP side, using the brackets will make the value come through as an array:
for ($x = 0; $x < $_POST['criteria']; $x++) {
// do something with each $_POST['criteria'][$x] and $_POST['description'][$x]
}
Use jQuery to add an onClick Listener and add the fields:
$("#button").on("click", function() {
$("#containertoappend").append('<input type="text" id="anothercriteria" placeholder="Another criteria">');
$("#containertoappend").append('<textarea id="anotherdescription" placeholder="Another Description"></textarea>');
});

Use LIKE operator to select all checkboxes that match pattern

I need a little guidance. I have an HTML form comprised of a very long list of items pulled from an array generated by a database query (it's a list of university courses). Users need to be able to select as many or as few courses as are relevant to their research: because the list can have hundreds or items I have a "select all" and a "select none" function and have added a jQuery shift-select batch selector to make this as easy as possible.
However, I also want them to be able to enter some text in an input box and click APPLY to select all checkboxes where the label text pattern matches using a LIKE operator (i.e., if they want all MATH courses, or all courses of level 2xx). The project is using PHP and JavaScript/jQuery/AJAX.
I know how to pull from the database based on LIKE queries, but I'm just a bit stumped as to how best loop through the generated form and target the items that are in my form. (My PHP is pretty strong, my jQuery is a bit shaky).
The list of checkboxes is generated via a loop through the array with each item set up as follows:
$o .= '<input id="'.$rw[2].'_'.$rw[0].'"
type=checkbox name="' . $rw[2].'_'. $rw[0]. '" />';
$o .= '<label for="'.$rw[2].'_'. $rw[0].'"> ' . $rw[1] . '</label>';
$o .= '</td>';
So we end up with a simple checkbox form with a LABEL FOR and the label text, and the items are all named as the array keys.
This is the HTML output for a typical item:
<tr><td><input id="110_105" type=checkbox name="110_105" />
<label for="110_105"> PHIL233</label></td></tr>
Sorry if this description is a bit long, but what I need is an idea of how to go about looping through the form's elements after it is generated to SELECT the checkbox for every item where the pattern matches.
Hope this makes sense!
Tamra
This situation is perfect for using AJAX to filter the checkbox list. I highly advocate for this instead.
But if you need to filter on the client it's fairly easy with JavaScript.
//give the labels a class so they are easy to find
var labels = document.getElementsByClassName('course-name');
//filtering text field
var query = document.getElementById('query');
//'apply' button
var queryBtn = document.getElementById('query-submit');
queryBtn.addEventListener('click', function() {
for (var i = 0; i < labels.length; i += 1) {
var label = labels[i];
var text = label.innerText;
if (text === query.value) {
label.previousElementSibling.checked = true;
}
}
}, false);
You can try it with jQuery find method.
http://api.jquery.com/find/
With it and the "Attribute Contains Selector", you can do the trick.
http://api.jquery.com/attribute-contains-selector/

PHP multiple records insert

I am attempting to reword my issue.
I have a datatable that can return thousands of records, each with multiple columns. There is a checkbox in the first column that, once the user checks it, they then click a button, and the CONTAINER_NUMBER that is associated with the row is sent to a modal window to be used in a form.
Here is the code for the checkbox:
echo "<tr><td><input type=\"checkbox\" id=\"{$Row[CONTAINER_NUMBER]}\" name=\"checkMr[]\" /></td>";
This is the javascript that retrieves the CONTAINER_NUMBER and sends it to the modal window:
<script type="text/javascript">
$(function()
{
$('a').click(function()
{
var selectedID = [];
$(':checkbox[name="checkMr[]"]:checked').each(function()
{
selectedID.push($(this).attr('id'))
});
$(".modal-body .containerNumber").val( selectedID );
});
});
</script>
This is the section of the modal window that displays the CONTAINER_NUMBER:
<div class="modal-body">
<form action="" method="POST" id="serviceModalForm" name="serviceModalForm">
<input type="text" name="containerNumber" id="containerNumber" class="containerNumber">
Here is the section of PHP that takes the id="containerNumber" and converts it to a PHP variable. After that, there is an INSERT statement that inserts the containerNumber into a database table:
<?php
$container = $_POST['containerNumber'];
if(isset($_POST['submit'])){
$container = mysql_real_escapse_string(stripslashes($container));
$sql = "INSERT INTO myTable (container_num) VALUES ('$container')";
if(mysql_query($sql)){
echo "Insert complete";
}
else {
echo "Insert was not completed";
}
?>
This code is fine. It works good. It does what it's supposed to do...for when the user checks ONE checkbox. It DOES NOT work when the user checks multiple checkboxes.
Basically, from what I've been researching is that I need to separate the records from the variable $container, as there can be multiple containers in that variable, which is why the query does not work when there are more than one container numbers selected.
I need to be able to separate the container numbers and store them in an array or something. The query will read each record separately and generate multiple INSERT statements for each record.
I've tried several times to create an array and get the sql statement to recognize it, but have been unsuccessful. I'm not sure if I'm placing the array in the right place. I'm not sure if this has to be done in the javascript before the container gets sent to the modal window.
I know I need to utilize a FOREACH loop to go through the array, but like I said, I'm not sure where the array needs to go in my code.
Please help. I know I need to learn PDO or MYSQLI. I will be sure to utilize PDO or MYSQLI on my next application. Until then, please help me with this issue.
Thank you, and sorry for so much wording.
Your containerNumber will be posted as a converted string from a js array. Something like id1, id2, id3[...]
In your php code, convert the $container back to an array ($containerArray = explode(",", $container)) and construct the sql dynamically to add all the rows in a single query so that the statment becomes something like
INSERT INTO myTable (container_num) VALUES ('$containerArray[0]'), ('$containerArray[1]')[...]

cakephp - Javascript

We are working on an application using the CakePHP framework
Basically, its a questionnaire application and it has a few dependant questions, i.e. based on a response to a specific question, it needs to show or hide the next one
For e.g.
Question: Are you married? Yes/No
If the user selects Yes, then using javascript the next question gets displayed for user input
Question: Spouse's name
Saving this information is fine, but when editing, when populating the form, we would want to be able to display the fields for which user has inputted data - in this case, it needs to show the field that has the spouse's name
Since by default we are hiding the spouse name field, when editing, it doesn’t display the field, even though there is a value to it
Is there some way that CakePHP can handle this or does it require us to write some javascript to take care of this?
Thanks in advance.
CakePHP does not manage this for you. While CakePHP is very powerful and a great framework, it will not write this kind of logic for you. You must write it.
I would suggest making the EDIT screen different from the ADD screen. Build the list of values from the database and display the fields that have values (and include any empty fields that should require values).
Keep in mind reusable does not necessarily mean that all CRUD actions fit into the same view.
Like others I advise you use differents EDIT and ADD screens.
But you can try make it with Javascript like this:
<script>
function enableDisableField(targetFieldId){
var targetField = document.getElementById(targetFieldId);
var checkbox = event.target;
console.log(checkbox.checked);
if (checkbox.checked){
targetField.disabled = false;
targetField.value = "empyt";
}else{
targetField.disabled = true;
targetField.value = "empyt";
}
}
</script>
<label><input type="checkbox" onchange="enableDisableField('married')"/> Merried</label>
<?= $this->Form->input('married',['label' => false, 'disabled']); ?>
It works well for ADD, but if you and EDIT you have to change de disable value according a field value:
<label><input type="checkbox" onchange="enableDisableField('married')"/> Merried</label>
<?= $this->Form->input('married',['label' => false, !isset($user->married) ? 'disabled' : '' ]); ?>

Categories

Resources