I am using select2 and I want to handle on change event
it works well the first time, but when I append new select2 after every change and after appending new select2 on change does not work
$('select').on("select2:select", function(e) {
e.preventDefault();
var item_id = $("option:selected").data('id');
var product_id = $("option:selected").data('product');
$.ajax({
type: "post",
url: window.location.origin + '/product/get-items',
data: {
item_id: item_id,
product_id: product_id,
"_token": $('#csrf-token')[0].content //pass the CSRF_TOKEN()
},
success: function(data) {
$(".all-items").hide();
data.specifications.forEach(myFunction);
function myFunction(specification, index) {
var a = '<div class="all-items"><div class="mb-1"><div class="row py-1"><label style="font-size: 16px; margin: 10px; margin-bottom: 10px" class="py-1 mt-2">' + specification.name + ' :</label></div><div class="row"><select class="js-example-basic-single select-' + index + ' test' + index + ' item selectpicker selectItem" name="specification[]"> </div></div></div>';
$(".all").append(a);
specification.items.forEach(test);
function test(value, inx) {
if (data.itemIds.includes(value.id.toString())) {
var a = '<option style="font-size: 10px" data-id="e" data-product="dd" value="dd">' + value.name + '<span></span></option></select>';
$(".test" + index).append(a).select2();
}
}
}
}
});
});
I have to section for appending
first, append select2 and after this append options of each select
I want to use on change event for all select2 ( appending and initial )
the query selector $('select') collects only the current select elements in a document and not contains later elements appended to the document. So you need to use a more general selector to cover late elements. This should work:
$(document).on("select2:select","select",function(e) { })
Related
I'm using ajax to get an results from code behind, when I Get those results I'm creating an a divs. And this works fine, adding a div dynamically.
Now I Want to add on each div onclick event which should raise some method when it's clicked, so here is my full code:
<script>
function onSelectGroup(Id) {
$.ajax({
method: "GET",
url: "Product/GetProductsByGroupId",
data: { groupId: Id }
})
.done(function (response) {
$(".products").html("");
for (var i = 0; i < response.length; i++) {
//I wrote onclick = "addProduct(response[i])" to generate for each div each onclick event
let item = '<div class="col-md-3"> <div class="Product-holder" onclick="addProduct(' + response[i] + ')" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
//Trying to append it to my .product class because it's parent of this divs above
$(".products").append(item);
}})};
function addProduct(product) {
console.log(product.Title);
}
</script>
But when I click on any of my generated divs I get an following error:
Uncaught SyntaxError: Unexpected identifier
I'm looking for issue for 3h allready, and I'm really stucked here..
Any kind of help would be great.
Thanks
P.S
CODE BEHIND - C # METHOD:
public ActionResult GetProductsByGroupId(int groupId)
{
var products = ProductController.GetProductsByGroupId(groupId);
if(products)
{
List<Product> productlist = new List<Product>();
foreach (var item in products)
{
Product product = new Product();
product.ProductId = Convert.ToInt32(item.Id);
product.Price = Convert.ToDecimal(item.Price);
product.Title = item.Title;
productlist.Add(product);
}
return Json(productlist, JsonRequestBehavior.AllowGet);
}
return Json(products, JsonRequestBehavior.AllowGet);
}
Remove the onclick and use delegate, you are passing an object to a function which convert response[i] to text [Object object], use data-* attributes to hold data for each object and attach an event to the div with the class product, on click of the div we'll use $(this) to reference the current clicked div and access its data attributes.
$(".products").html("");
var response = [{ProductId:4, Title:"Doe", Price: 34.89}, {ProductId:6, Title:"Jane", Price: 20.99}];
for (var i = 0; i < response.length; i++) {
//I wrote onclick = "addProduct(response[i])" to generate for each div each onclick event
let item = '<div class="col-md-3"> <div class="Product-holder product" data-price="'+ response[i].Price +'" data-title="' + response[i].Title + '" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
//Trying to append it to my .product class because it's parent of this divs above
$(".products").append(item);
//console.log(item);
};
$(document).on('click', '.product', function(){
var product = {Title: $(this).data('title'), ProductId: $(this).attr('id'), Price: $(this).data('price')};
console.log(product);
// here use ajax to add this product
});
body {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="products"></div>
Take a look at the Delegate jquery method!
Description: Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.
So you basically need to bind the onClick event to the parent div, and pass a selector that will appear later on the child divs.
<script>
function onSelectGroup(Id) {
$.ajax(
//Do your ajax call here
).done(function (response) {
for (var i = 0; i < response.length; i++) {
let item = '<div class="event-target"></div>'
$(".products").append(item);
}})};
// Here's where the magic happens.
// We bind the event to the elements that have the 'event-target' class
//inside the element that have the 'products' class.
$('.products').on('click', '.event-target', function(){
console.log(this);
})
</script>
Warning: take care using delegate, if you use the wrong selector you can end up triggering the event for each element on the page, or even recursivelly (belive me, have made it a lot...)
Use data attributes to store any data & on click retrieve the data attribute.The code is not tested but hopefully it will work
let item = '<div class="col-md-3">' +
' <div class="Product-holder" ' +
'onclick="addProduct(this)"' +
' data-title="'+response[i].Title+'"' +
' id=' + response[i].ProductId + '>' +
'<img class="img-responsive" src="images/maxresdefault.jpg">' +
'<p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p>' +
'</div>' +
'</div>';
$(".products").append(item);
function addProduct(product) {
console.log($(product).data('title'));
}
Also you need to delegate the event since they are dynamically created element
$("body").on("click",".Product-holder",function(){
console.log($(product).data('title'));
})
In this case the inline event handler that is onclick function will be redundant
Let me going to explant your code.
for (var i = 0; i < response.length; i++) {
let item = '<div class="col-md-3"> <div class="Product-holder" onclick="addProduct(' + response[i] + ')" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
$(".products").append(item);
}})};
On these line of code, I saw that you have added strings to a variable.
but more exception response[i].ProductId seem like response[i] was an object.
but in Javascript you can't add an object to String by + operator, it will be return "string [object] string". What is solution for that??
Convert your object to JSON String like {"id": 123, "name": "Product name"}, that will show in html code like this onclick='addProduct({"id": 123, "name": "Product name"})' remember that onclick = ' not "
I am trying to get the todo titles from jsonplaceholder.typicode.com JSON. I have three buttons and each botton has and id, that id is related to the json todo. When you click on a botton you see the title of that json todo.
Button 1 = jsonplaceholder.typicode.com/todos/1 Button 2 =
jsonplaceholder.typicode.com/todos/2 etc..
$('button').click(function (event) {
var id = event.target.id;
console.log(id);
$.ajax({
url: "https://jsonplaceholder.typicode.com/todos/" + id,
type: "GET"
}).done(function (data) {
$('#result').append('<div class="todo"></div>');
$.each(data, function (key, value) {
if (key == "title") {
$('.todo').append('<p>' + key + ': ' + value + '</p>');
}
});
}).fail(function (event) {
alert(event.status);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="1">A</button>
<button id="2">B</button>
<button id="3">C</button>
<div id="result">
</div>
The problem is that titles repeat each time I click on a button. Why this occurs?
Why? Because you append another <div class="todo"></div> each time button is clicked and then append the content to every one that exists
You can isolate the new <div class="todo"> and only append the new content to that
var $todo = '<div class="todo"></div>'
$('#result').append($todo);
$.each(data, function(key, value) {
if (key == "title") {
$todo.append('<p>' + key + ': ' + value + '</p>');
}
});
Or empty the $('#result') before you add the new content if you don't want to see the first set by changing:
$('#result').append('<div class="todo"></div>');
To
$('#result').html('<div class="todo"></div>');
On each ajax done callback you first create a new todo div:
$('#result').append('<div class="todo"></div>');`
and after that, you add the result to all elements with a todo class:
$('.todo').append('<p>' + key + ': ' + value + '</p>');
I'd suggest removing the first line and changing the second to $('#result')
need an help on a jquery script.
I have a select that trigger from Ajax a list of options available. Once user click this option if a variable got 1 a HTML div is added, if i change to another value HTML disappear. This script work as well first time: i click a option and div appear, when i click other option disappear but this cycle is completed if i it another time select option this stop working...
This is the code:
<script type="text/javascript">
$(document).ready(function() {
request_url = 'opzioni-select';
$.ajax({
url: request_url,
success: function(data){
$('#id_opzione').html("");
$.each(data, function(i, item){
var id = item.id;
var parent_id = item.parent;
var nome_opzione = item.nome_opzione;
var nome_parent = item.nome_parent;
$('#id_opzione').append('<option data-opzione="'+ item.nome_parent +'" data-parent="'+ item.parent +'" id="' + item.nome_opzione +'" value="' + item.id + '">' + item.nome_opzione +'</option>');
});
$(document).on('change', '.opzione', function(){
var parent = $('#id_opzione').find(':selected').data('parent');
var nome_parent = $('#id_opzione').find(':selected').data('opzione');
if(parent != null) {
$('#parent-div').append('<label for="parent-div" class=" control-label col-md-4 text-left">'+ nome_parent +'</label><div class="col-md-6"><input type="text" name="valore_parent" class="form-control"></div><div class="col-md-2"></div>');
} else {
$('#parent-div').hide('fast');
}
});
}
});
});
</script>
I tried to change div id in class and switched to "on('change" instead of call directly the #div with .change( but nothing.
Few problems - you're appending a bunch of options - then delegating for a class that i cant see being created.. Id recommend moving the delegated event to the document ready function. . and using the id of the select - and selecting the option after that using this.
<script type="text/javascript">
$(document).ready(function() {
request_url = 'opzioni-select';
$.ajax({
url: request_url,
success: function(data){
$('#id_opzione').html("");
$.each(data, function(i, item){
var id = item.id;
var parent_id = item.parent;
var nome_opzione = item.nome_opzione;
var nome_parent = item.nome_parent;
$('#id_opzione').append('<option data-opzione="'+ item.nome_parent +'" data-parent="'+ item.parent +'" id="' + item.nome_opzione +'" value="' + item.id + '">' + item.nome_opzione +'</option>');
});
});
$('#id_opzione').on('change', function(){
alert('Changed');
var parent = $('#id_opzione').find(':selected').data('parent');
var nome_parent = $('#id_opzione').find(':selected').data('opzione');
if(parent != null) {
$('#parent-div').append('<label for="parent-div" class=" control-label col-md-4 text-left">'+ nome_parent +'</label><div class="col-md-6"><input type="text" name="valore_parent" class="form-control"></div><div class="col-md-2"></div>');
} else {
$('#parent-div').hide('fast');
}
});
}
});
</script>
Here in my code i uses the jquery to load data from database with n-level performance .
But when i change the parent dropdown all next elements not going to remove please help.
Thank you in advance
$(document).ready(function() {
$(document).on('change', '#subcat', function() {
var id = $(this).val();
$(this).nextAll('.remove').remove();
var options = "<option value=0>--select subcategory--</option>";
$.ajax({
type: 'get',
url: '/category/' + id + '/dropDownDynamic',
success: function(responseText) {
if (responseText != "") {
$.each(responseText, function(index, value) {
options += '<option value=' + index + '>' + value + '</option>'
});
$('#subcatCustom').append('<div class="form-group marginRemove remove"><label class="col-sm-2 control-label">Select SubCategory:</label><div class="controls col-sm-5"><select name="parent" id="subcat" class="form-control">' + options + '</select></div></div>');
}
},
});
});
});
this line not working.
$(this).nextAll('.remove').remove();
Because they are not sibling of the current subcat element, they are siblings of current .remove so try
$(this).closest('.remove').nextAll('.remove').remove();
In your event handler this refers to the #subcat element, which is a descendant of .remove element, so we uses .closest() to find the .remove ancestor of this, then find that ancestor's next siblings
Note: ID of an element must be unique, so use subcat as a class instead of ID.
I have the following script that creates a list of names :
setInterval(function() {
$.ajax({
type: "GET",
url: "<?php echo base_url(); ?>cashier/walkin_patient_payments",
dataType: "JSON",
success: function(payment_list) {
pat_payment_list = $('#walkin_patient_payment').empty();
if (payment_list === null) {
} else {
$.each(payment_list, function(i, payment_list) {
pat_payment_list.append('<li><i class = "glyphicon glyphicon-user"> </i>' + payment_list.walkin_patient_name + '<span style="color:red !important;"> Kshs : ' + payment_list.amount + '</span>\n\
<input type="hidden" id="walkin_id_list" name="walkin_id_list" class="walkin_id_list" value="' + payment_list.walkin_id + '"/>\n\
</br></li>');
});
}
},
error: function(data) {
//error do something
}
});
}, 3000);
Which is appended to the following UL list :
<ul class = "dashboard-list walkin_patient_payment" id="walkin_patient_payment">
</ul>
But when I try to run the following script that is supposed to pick individual walkin id from the list it only gives the value of the first list even when I click the number 5th list.
Below is the script :
$('.walkin_patient_payment').on('click', '.walkin_payment_link', function() {
//get
var walkin_id = $(this).closest('ul').find('input[name="walkin_id_list"]').val();
alert(walkin_id);
});
What is the best way to implement this? What am I doing wrong?
That is because you are traversing to ul element and .find('input[name="walkin_id_list"]') will return all the inputs with name walkin_id_list in ul. and using .val() on collection of elements will only return the value of first element.
You need to use .closest('li') instead of .closest('ul'):
var walkin_id = $(this).closest('li').find('input[name="walkin_id_list"]').val();
Also note that you are generating the elements with same ids. IDs should always be unique. You can rather use same class instead.
You can implement click directly on li
$('.walkin_patient_payment li').click(function () {
var walkin_id = $(this).find('input[name="walkin_id_list"]').val();
alert(walkin_id);
});