PHP doesn't see new elements created with jQuery and AJAX - javascript

I faced an issue since I can't get a just created element with a PHP script.
I have a list of tags loaded with PHP:
<ul>
<li>
<input class="adm-checkbox" type="checkbox" name="check_list_tags[]" value="4">
Some tag
<li>
<ul>
Thanks to AJAX I append another element inside the UL
jQuery(document).ready(function($) {
$('.add-tag-btn').click(function(event) {
var tag_title = $('.tag-search').val();
$.ajax({
url: 'add-tag.php',
type: 'POST',
dataType: 'json',
data: {
'tag_title': tag_title
},
success:function(result){
$('.tag-search').val('');
$('.new-tags').append('<li><input class="adm-checkbox" type="checkbox" name="check_list_tags[]" value="'+result.tag_id+'">'+tag_title+'</li>');
console.log(result.tag_id);
}
});
});
});
Thus I have a new UL
<ul>
<li><input class="adm-checkbox" type="checkbox" name="check_list_tags[]" value="4">Value #4</li>
<li><input class="adm-checkbox" type="checkbox" name="check_list_tags[]" value="5">Value #5 (new value generated with jQuery and AJAX)</li>
</ul>
But once I submit the form, only the existed value is added to DB.
if (isset($_POST['submit'])) {
....
bla bla bla
foreach ($_POST['check_list_tags'] as $value) {
$arr2[] = $value;
}
bla bla bal
}
Looks like that PHP can't handle a new value without the page reloaded. At the same time, I add
checked="checked"
dynamically and that works just perfect.
Can anyone explain me how to force PHP to see the newly created elements (the elements that were appended to the existed HTML by the means of jQuery).
Thanks everyone for the assistance.
upd:
This is how I add the "checked"
jQuery(document).ready(function($) {
$('.adm-checkbox').click(function(event) {
if (this.checked) {
this.setAttribute("checked", "checked");
console.log('checked');
} else {
this.removeAttribute("checked");
}
});
});
This is how the form looks like:
<form class="" action="<?php echo $router->url ?>" method="post" enctype="multipart/form-data">
.....
<ul class="new-tags">
</ul>
<ul>
<?php foreach ($admin->getAdmTags() as $value): ?>
<li><input class="adm-checkbox" type="checkbox" name="check_list_tags[]" value="<?php echo $value['id'] ?>"><?php echo $value['title'] ?></li>
<?php endforeach; ?>
<ul>
</form>
UPD # 2:
May be the reason is that I use two separate functions in jQuery for "checked"??!?!
$('.adm-checkbox').click(function(event) {
if (this.checked) {
this.setAttribute("checked", "checked");
console.log('checked');
} else {
this.removeAttribute("checked");
}
});
and
$('.adm-tags').on('click', '.adm-checkbox', function(event) {
if (this.checked) {
this.setAttribute("checked", "checked");
console.log('checked');
} else {
this.removeAttribute("checked");
}
});
I do it because onclick doesn't work for the newly created elements.
P.s: It doesn't matter where I put a newly created "li"...
Thank everyone for participation. I've created a new page and did everything again. And now it works. Now I need to find the mistake in my full code.

Name attributes can be arrays so the name isn't the issue - HTML input arrays
I think the reason is as you mentioned, the checked attribute needs to be added to all of the inputs otherwise the value won't be sent in the request.
If the inputs were text or number for example, then the checked attribute wouldn't be needed.
The same would apply to radio inputs, or the selected attribute for a select menu.
TLDR, add checked:
$('.new-tags').append('<li><input class="adm-checkbox" type="checkbox" name="check_list_tags[]" value="'+result.tag_id+'" checked>'+tag_title+'</li>');
That is of course, if it should be automatically checked and not reliant on the user checking it manually.
I may have to change this answer based on if this is a traditional form submission or an ajax submission not using a form.

I don't know how to close the topic. It works with the newly created code. Once I find out the mistake in my full code, I will reply with the explanation of my mistake.

When you send a form though either POST or GET every input needs a unique name. From you code it looks like you add a new input element with a name attribute that has the same value as the already existing element.
I suspect if you add the new element with a unique name value it should work. You could incorporate that into you JavaScript code by having a counter for the number of input elements with name X and then add a number. And you would need to do a similar thing in your PHP.
Edit: Apparently you can have name attributes with the same name if you use '[]' after the name, thank you #martincarlin87

Related

Dynamically send javascript value via form

I don't know if it's possible, but I need to send some information across a form ou inside url come from checkbox value.
This code below is inside a products loop and create a checkbox on every products (product comparison approach).
In my case, it's impossible to make this code below across a form.
<?php
echo '<div><input type="checkbox" value="' . $products_id .'" id="productsCompare" title="Compare" onclick="showProductsCompare()" /> Compare</div>';
?>
To resolve this point, I started to use an ajax approach and put the result inside a $_SESSION
My script to for the checbox value
$(function() {
$('input[type=checkbox]').change(function() {
var chkArray = [];
$('#container').html('');
//put the selected checkboxes values in chkArray[]
$('input[type=checkbox]:checked').each(function() {
chkArray.push($(this).val());
});
//If chkArray is not empty create the list via ajax
if (chkArray.length !== 0) {
$.ajax({
method: 'POST',
url: 'http://localhost/ext/ajax/products_compare/compare.php',
data: { product_id: chkArray }
});
}
});
});
And at the end to send information on another page by this code. Like you can see there is no form in this case.
<div class="col-md-12" id="compare" style="display:none;">
<div class="separator"></div>
<div class="alert alert-info text-md-center">
<span class="text-md-center">
<button class="btn">Compare</button>
</span>
</div>
</div>
No problem, everything works fine except in my compare.php file, I have not the value of my ajax. I inserted a session_start in ajax file
But not value is inserted inside compare.php.
I tried different way, include session_start() inside compare.php not work.
My only solution is to include in my products file a hidden_field and include the value of ajax across an array dynamically, if it's possible.
In this case, values of hidden_fields must be under array and sent by a form.
This script must be rewritten to include under an array the chechbox value
without to use the ajax. How to insert the good code?
$(function() {
$('input[type=checkbox]').change(function() {
var chkArray = [];
$('#container').html('');
//put the selected checkboxes values in chkArray[]
$('input[type=checkbox]:checked').each(function() {
chkArray.push($(this).val());
});
//If chkArray is not empty show the <div> and create the list
if (chkArray.length !== 0) {
// Remove ajax
// some code here I suppose to create an array with the checkbox value when it is on true
}
});
});
and this code with a form
<?php
echo HTML::form('product_compare', $this->link(null, 'Compare&ProductsCompare'), 'post');
// Add all the js values inside an array dynamically
echo HTML::hidddenField('product_compare', $value_of_javascript);
?>
<div class="col-md-12" id="compare" style="display:none;">
<div class="separator"></div>
<div class="alert alert-info text-md-center">
<span class="text-md-center">
<button class="btn">Compare</button>
</span>
</div>
</div>
</form>
Note : this code below is not included inside the form (no change on that).
<?php
echo '<div><input type="checkbox" value="' . $products_id .'" id="productsCompare" title="Compare" onclick="showProductsCompare()" /> Compare</div>';
?>
My question is :
How to populate $value_of_javascript in function of the checkbox is set on true to send the information correctly inside compare.php
If my question has not enought information, I will edit this post and update in consequence.
Thank you.
You cannot pass JavaScript Objects to a server process. You need to pass your AJAX data as a String. You can use the JavaScript JSON.stringify() method for this...
$.ajax({
method: 'POST',
url : 'http://localhost/ext/ajax/products_compare/compare.php',
data : JSON.stringify({product_id: chkArray})
});
Once that has arrived at your PHP process you can turn it back into PHP-friendly data with PHP JSON methods...
<?
$myArray = json_decode($dataString, true);
// ... etc ... //
?>
See:
JSON # MDN
JSON # PHP Manual
Example: Form Submission Using Ajax, PHP and Javascript

get href from php and use element in JQuery

I have xyz.php and working menu <li> elements. I need to get hreffrom php use it in Java script for navigate away. So I have list of li tag and in code it's displaying one for example. Each li tag has unique href.
My question is: If I have select only one li elements from the list. I want to use that li's associated href in IF condition in JavaScript and ELSE part is multiple Li's selected. The code is working for else part. But, I am having issue with IF part.
I am not getting the href value from PHP. you can get 'href'from $xyz['url'] in php.
xyz.php
<div class="global-wrapper">
<ul class="list">
<li>
<input id="retreat-<?php echo $xyz['api_id']; ?>" class="custom-check-input more-filter-experience" type="checkbox" value="<?php echo $xyz['name']; ?>" data-home-location="<?php echo $xyz['api_id']; ?>">
<label class="custom-check-label" for="retreat-<?php echo $xyz['api_id']; ?>"></label>
</li>
</ul>
</div>
Here, the java script code:
xyz.js
if(retreatIdArray.length === 1 && exploreDate === undefined) {
var categoryId = $('.global-wrapper').find('.loadProducts').attr('data-categoryid');;
window.location.href = "/categoryId"; // having issue
} else{
window.location.href = '/destination';
}
You wrote undefine instead of undefined. The statement inside if will never be true.
Also, to check for undefined, it's better to use typeof.
if(retreatIdArray.length === 1 && typeof exploreDate == 'undefined') {
retreats = $('.global_wrapper').find('.custom-check-input').val();
window.location.href = '/href';
} else {
window.location.href = '/destination';
}
Note: untested code, you may have to adjust it to your needs. Please let me know if it works.

why after the 3rd click my function doesn't work?

I have the following html code:
<?php foreach ($this->tags as $uri=>$tag){?>
<input type="checkbox" name="tags[]" style="display: none;" value="<?php echo $uri;?>" id="create_<?php echo $uri;?>" <?php echo isset($args['tags']) && in_array($uri, $args['tags'])?'checked="checked"':'';?> />
<span onclick="selectTag(this.id)" id="create_<?php echo $uri;?>" for="create_<?php echo $uri;?>" class="tag <?php echo isset($args['tags']) && in_array($uri, $args['tags'])?'selected':'';?>"><?php echo str_replace(' ', ' ', $tag);?></span>
<?php }?>
And here is my JS code:
function selectTag(id) {
var input = '.tags input#'+id;
var span = '.tags span#'+id;
if ($(input).is(':checked') && $(span).hasClass('selected')) {
$(span).removeClass('selected');
$(input).attr('checked', false);
}
else {
$(span).addClass('selected');
$(input).attr('checked', true);
}
}
When I click on a span box, selects the box, and when I click again on it, it unselects it. The problem is, that after the 3rd time, it just stops working.
What is wrong with my code that is not working?
JQuery now has a prop method that is a slightly better alternative to using the attr method.
Try replacing your calls with attr("checked", true); with calls to prop("checked", true);
See here for documentation on prop: http://api.jquery.com/prop/
Here for a discussion between the two: .prop() vs .attr()
Edit:
Also, as Ed Cottrell stated, you'll want to have UNIQUE id attributes for all your elements on your page.
Edit2:
I have created a fiddle that demonstrates this usage: http://jsfiddle.net/xDaevax/E39hc/
You are giving the input and the span the same id attribute. Ids must be unique per element; you cannot have an input and a span the same id. Doing it this way will cause all sorts of problems, including the behavior you are experiencing. Give one of them a slightly different id (like create_<?php echo $uri;?>_span).
Also, as #xDaevax says, you should use .prop rather than .attr -- I have had the same problem when using .attr.

On unchecking a checkbox trigger an event

I have following code
<li>
<input type="checkbox" value="1" class="filter" name="Bedroom">
<a id="1" href="javascript:void(0)" class="filter1"> Bedroom </a>
</li>
<li>
<input type="checkbox" value="7" class="filter" name="Living Room">
<a id="7" href="javascript:void(0)" class="filter1"> Living Room </a>
</li>
<li>
<input type="checkbox" value="6" class="filter" name="Corridor">
<a id="6" href="javascript:void(0)" class="filter1"> Corridor </a>
</li>
</ul>
java script
<script>
var id='';
jQuery('.filter').click(function(){
jQuery('.filter').each(function(){
if(jQuery(this).attr('checked'))
{
id+=jQuery(this).val()+',';
}
});
alert(id);
jQuery.get('<?php echo $this->getUrl('some url') ?>',{cat:id},function(data){
jQuery('#id').html(data);
});
});
</script>
Suppose I checked a checkbox I am getting the id of that check box.
id+=jQuery(this).val()+',';
How to remove the the id of element on unchecking a checkbox from id variable ?
I am trying to make an ajax call,When I click on the check boxes then I should get
a url containing the ids of the checkboxes example .../?cat=7%2C7%2C6%2C
and on unchecking the check boxes those check boxes ids should not be present
You will be creating duplicate ids in the list, an easy solution is to recreate the id string every time like
var id;
var $checks = jQuery('.filter').change(function () {
id= $checks.filter(':checked').map(function () {
return this.value;
}).get().join(', ');
console.log(id);
});
Demo: Fiddle
If I understand your question correctly, below is the javascript that you are looking for:
var id='';
$('.filter').click(function(){
id='';
$('.filter').each(function(){
if(this.checked)
{
id+=$(this).val()+',';
}
});
alert(id);
});
I think the key is to re-initialize the id variable to blank, so you do not keep adding values to it.
jsFiddle for working example
Don't use a String, but use an array:
var ids = new Array();
For the check don't use the click event, but the change event:
$(".filter").change(function() {
if ($(this).prop("checked") == true) {
// Add the id to the list
ids.push($(this).attr("id")); // Note the attribute, not the val()!
} else {
var index = -1;
$.each(ids, function(idx, value) {
if (value == $(this).attr("id")) index = idx;
});
ids.splice(idx, 1); //Remove the id
}
}
Consider another approach.
var ids = [];
jQuery('.filter').change(function(){
ids = []; // Reinitialize array
jQuery('.filter:checked').each(function(){
ids.push(this.value);
});
alert(ids.join(',')); // Stringifies your array, using a comma as a separator.
});
// You have access to ID's in outer scope as well!
Some may consider it a "performance hit" by reinitializing every time,
but seeing as you only have very few checkboxes, I see no problem.
Your original question text was:
How to remove the id of element on unchecking a checkbox?
Answer:
jQuery('.mySelector').each(function() {
jQuery(this).removeAttr('id');
}
You may test this snippet on any website that loads jQuery, i.e. jquery.com - open in browser, hit F12 and paste this into the console (and watch it destroy the whole CSS ;) ):
$('div').each(function() { $(this).removeAttr('id'); }
Update:
From reading your updated question, i believe what you are asking for is pretty much covered by the answers above.
My two cents: id was (and still is) amiguous in your question context, better names for the variable would be ids, csvIdString, concatenatedCheckboxIds, or whatever describes the variable best in its context (following Clean Code Philosophy)

reading a drag and drop ordered list via JavaScript

I have an application (drag and drop using JqueryUI.GridSort) that allows the user to upload photos, and then sort the photos in the order that they would like using drag and drop.
On page load, the user is prompted to upload photos which are posted to the next page. When they arrive on the next page my php script creates a <ul id="sortable"> containing <li> for each of the files they uploaded. For each picture that they have uploaded to the site, a new <li> is created. Inside of that <li> is a <img> that sets the picture for <li> with the image they have uploaded.
My goal is to be able to "save" the order of the pictures after they have arranged them in the drag and drop interface. For example, once they have finished arranging and sorting the pictures in the order they want them in, I would like to be able to send them another page that creates an xml file ( I don't need help with the XML, only saving the order) with using the list that they created in the correct order.
After hours of tinkering with PHP, I have come to realization that because PHP is a serverside language, it cannot see what is sorted post render. So my question is, is there a way to have JavaScript or Ajax read the current order of the list, and post it to the next page? If you do know how, could you please provide an example of both the POST from one page, and the post receiving on the other? I am not very familiar with Ajax.
Thank you greatly for any assistance you could provide.
Sample Code (The contents of the foreach statement that creates a LI for each file uploaded)
$imgID++;
echo '<li class="ui-state-default"><img id="'.$imgID.'"'.' src="user_files/'.$file_name.'" draggable="true" height="90" width="95"></li>';
EDIT
main page :
<script>
$('#my_form').on('submit', function() {
var ordered_list = [];
$("#sortable li img").each(function() {
ordered_list.push($(this).attr('id'));
});
$("#ordered_list_data").val(JSON.stringify(ordered_list));
});
</script>
<div id="tesT">
<form id="my_form" action="update_data.php">
<!-- other fields -->
<input type="hidden" id="ordered_list_data"></input>
<input type="submit" value="Proceed to Step 2"></input>
</form>
</div>
update_data.php:
<?php
// process other fields as normal
if(isset($_POST['ordered_list_data'])) {
$img_ordering = json_decode($_POST['ordered_list_data']);
echo "1";
} else {
echo "nodata";
}
// do things with the data
?>
I built a JSFiddle doing basically the same thing that David posted.
I added a piece to write out the result to a div on the page, so you can see what's going on:
<input type="button" id="savebutton" value="save"/>
<div id="output"></div>
<form id="listsaveform" method="POST" action="script.php">
<input type="hidden" name="list" id="hiddenListInput" />
</form>
Javascript:
$(function() {
$( "#sortable" ).sortable();
$( "#sortable" ).disableSelection();
$( "#savebutton" ).click(function() { LISTOBJ.saveList(); });
});
var LISTOBJ = {
saveList: function() {
var listCSV = "";
$( "#sortable li" ).each(function() {
if (listCSV === "") {
listCSV = $(this).text();
} else {
listCSV += "," + $(this).text();
}
});
$("#output").text(listCSV);
$("#hiddenListInput").val(listCSV);
//$("#listsaveform").submit();
}
}
If you're using a <form> you can do something like this (assuming jQuery is being used):
$('#my_form').on('submit', function() {
var ordered_list = [];
$("#sortable li img").each(function() {
ordered_list.push($(this).attr('id'));
});
$("#ordered_list_data").val(JSON.stringify(ordered_list));
});
In essence, what you're doing is looping over the <ul>, fetching each <img> and appending the ids (in order of appearance) to an array. Arrays preserve ordering in JavaScript and JSON, so one can turn it into a JSON string using the JSON.stringify function, set it as the value of a <input type="hidden"> field and then submit the form.
If you want to use AJAX, the functionality is very similar. However, instead of using an onsubmit (or onclick) you'd use $.post.
Let's go with the <form> option since it's simpler. All told you'll have something similar to the above JS along with HTML like this:
<form id="my_form" method="post" action="./update_data.php">
<!-- other fields -->
<input type="hidden" name="ordered_list_data" id="ordered_list_data"></input>
<input type="submit" value="Submit"></input>
</form>
Then, in update_data.php (or whatever your script is named):
<?php
// process other fields as normal
if(isset($_POST['ordered_list_data'])) {
$img_ordering = json_decode($_POST['ordered_list_data']);
} else {
// handle case where there is no data
}
// do things with the data
?>

Categories

Resources