I have a working row clone scenario (multiple dynamic rows) after an inventory number is confirmed from mysql database. What I want to do (but can't figure out), is how to insert the inventory data to only the next DIV batch_item_desc which has the same class name as all because of the clone. What keeps happening is the inventory data is inserted to every row, and not "this" row.
HTML :
<div class="multi-field-wrapper">
<div class="multi-fields">
<div class="multi-field row">
<div class="col-md-2 item_num_div">
<div class="form-group">
<input type="text" class="form-control input-sm batch_item_num"
name="item_num[]">
</div>
</div>
<div class="col-md-2 batch_item_desc"></div>
<div class="col-md-2">
<button type="button" class="btn btn-danger remove-field btn-sm">
<span class="glyphicon glyphicon-minus"></span>
</button>
</div>
</div> <!-- End Div multi-field && row -->
</div> <!-- End div multi-fieldS -->
</div> <!-- end div wrapper -->
jQuery:
$('.multi-field-wrapper').each(function() {
var $wrapper = $('.multi-fields', this);
$('.multi-field .remove-field', $wrapper).click(function() {
if ($('.multi-field', $wrapper).length > 1)
$(this).parent('.multi-field').remove();
});
//-------- Batch Inventory --------------
$(".batch_item_num", $(this)).keyup(function(e) {
var item_num = $(this).val();
if (item_num.length == 9) {
$.get('inventory/api.php', {"action":"batch_item_num","item_num":item_num},
function(data, result) {
var desc = data;
$('.item_num_div').next('.batch_item_desc').html(desc);
$('.multi-field:first-child', $wrapper).clone(true).appendTo($wrapper).find('input').val('').focus();
});
}
});
});
I can't for the life of me get this line working to display inventory data for JUST the single row in question, it inserts to all rows.
$('.item_num_div').next('.batch_item_desc').html(desc);
You should use the current jQuery element $(this) instead of the class item_num_div selector that will select all elements with this class :
$(this).next('.batch_item_desc').html(desc);
Also you should go up to the parent row then select the batch_item_desc since it not a sibling of batch_item_num :
$(this).closest('.row').find('.batch_item_desc').html(desc);
Note that the $(this) inside the $.get callback doesn't refer to the current element no more, you should store the $(this) in another variable before the request e.g :
var item_num = $(this).val();
var _this = $(this);
Then use this variable instead of $(this) inside the callback :
_this.closest('.row').find('.batch_item_desc').html(desc);
Hope this helps.
You could use .first() to only select the first element in the set of matched elements:
$('.item_num_div').next('.batch_item_desc').first().html(desc);
Related
I tried to get value from input text with jQuery, but I only got the first value. Input text is looped.
Here's the HTML:
<div class="item-container-add">
#foreach($cartCollection as $cart)
#if($cart['name'] != 'asdfghjklkjgfds123890')
<div class="row row-add mr-1">
<div class="col-sm-6">
<input type="text" class="id_delete" name="id_delete" id="id_delete" value="{{ $cart['id'] }}">
</div>
<div class="col-sm-2 border-cart">
<button class="btn btn-del delete_button" name="delete_button" type="submit">Hapus<img class="icon-delete" src="./svg/delete.svg"></button>
</div>
</div>
#endif
#endforeach
</div>
From those HTML, I've got 4 different IDs with their own delete button. When I try to click Delete, my jQuery function only get the first ID from those loop. It is supposed to get the ID where I click the button. Here's my jQuery function:
$(document).on('click', '.delete_button', function(e) {
var a = $("#id_delete").val();
alert(a);
$.ajax({
/* some ajax function */
});
});
Image reference: https://imgur.com/mX1WHwM
Firstly you need to remove the id attributes from the HTML elements you create in the loop. id values must be unique within the DOM. Use the common classes on the elements to select them instead.
The reason for your problem is because in the click event handler you're selecting the element by its id. As this is a duplicate, only the first element with that id is found, hence you only ever get the first value. To address this you can use the this keyword in the click event handler to refer to the element which raised the event. Then you can use DOM traversal methods, such as closest() and find(), to retrieve the value from the related field. Try this:
<div class="item-container-add">
#foreach($cartCollection as $cart)
#if($cart['name'] != 'asdfghjklkjgfds123890')
<div class="row row-add mr-1">
<div class="col-sm-6">
<input type="text" class="id_delete" name="id_delete" value="{{ $cart['id'] }}">
</div>
<div class="col-sm-2 border-cart">
<button class="btn btn-del delete_button" name="delete_button" type="submit">Hapus<img class="icon-delete" src="./svg/delete.svg"></button>
</div>
</div>
#endif
#endforeach
</div>
$(document).on('click', '.delete_button', function(e) {
var a = $(this).closest('.row').find('.id_delete').val();
console.log(a);
});
Firstly, ID needs to be unique. You can refactor your code as below.
$(document).on('click', '.delete_button', function(e) {
var val = $(this).val();
var id = $(this).attr('id');
console.log(val, id);
});
$(document).on('click', '.delete_button', function(e) {
var a = $(this).closest('.row').find('input.id_delete').val();
console.log(a);
});
That takes the button you clicked, this, and finds the nearest ancestor matching .row, looks through the descendants to find the matching input.
I have a modal window used to update or add a new object Store.
This modal has a cascading dropdownlist for two properties: Department and District.
How should it work:
We first identify if we are in the situation of creating or updating a Store.
In case is a new Store the modal opens and using jQuery we present a default value for the District dropdownlists (since no Department has been chosen yet).
<script type="text/javascript">
var wasclicked = 0;
var $this = this;
$(document).ready(function () {
document.getElementById("modalbutton").onclick = function () {
//is AddNew Store button is hitted, this var = 1
wasclicked = 1;
};
$('#modal-action-store').on('hidden.bs.modal', function () {
//global.wasclicked = 0;
wasclicked = 0;
$(this).removeData('bs.modal');
});
$('#modal-action-store').on('shown.bs.modal', function (e) {
console.log($('#DistrictID').length);
//if wasclicked equals 1 that means we are in the AddNew Store scenario.
if (wasclicked == 1) {
//a default value is sent to District dropdownlist
var items = "<option value='0'>-- Seleccione Distrito --</option>";
$('#DistrictID').html(items);
};
});
});
</script>
However, at this moment, after the default value is added, after a fraction of a second, the value gets deleted.
What I've tried
I've noticed that when I remove this line of code:
$(this).removeData('bs.modal');
From the previous script, it works ok, but I need that code in order to clear the data from the modal if I need to use the modal to edit another Store.
Plus, when I debug the project the debugger did not stop at the breakpoint of that line, so I'm not sure why it's somehow executing in the background? Is it because it's wrapped inside the function document.ready()?
I've been struggling with this for days. I thank for any helpful comment.
Aditional info:
Online version of the project:
There is an online version for this for debugging:
http://plataformafantasypark.azurewebsites.net/
user: adelgado password: $Adelgado33
Under the menu 'Tiendas' -> 'Registro'
Button that calls the modal:
<div class="btn-group" id="modalbutton">
<a id="createEditStoreModal" data-toggle="modal" asp-action="Create"
data-target="#modal-action-store" class="btn btn-primary">
<i class="glyphicon glyphicon-plus"></i> NEW STORE
</a>
</div>
The Modal:
#model Application.Models.ApplicationviewModels.StoreIndexData
#using Application.Models
<form asp-action="Create" role="form">
#await Html.PartialAsync("_ModalHeader", new ModalHeader
{ Heading = String.Format("ActualizaciĆ³n de Modelo: Tiendas") })
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="modal-body form-horizontal">
<div class="form-group">
<label asp-for="DepartmentID" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="DepartmentID" class="form-control"
asp-items="#(new SelectList(#ViewBag.ListofDepartment,"DepartmentID","DepartmentName"))"></select>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Distrito</label>
<div class="col-md-10">
<select class="form-control" id="DistrictID" name="DistrictID" asp-for="DistrictID"
asp-items="#(new SelectList(#ViewBag.ListofDistrict,"DistrictID","DistrictName"))"></select>
</div>
</div>
{... more elements}
</div>
</form>
Why not do something like(?):
$("#modalbutton").on('click', function () {
//is AddNew Store button is hitted, this var = 1
wasclicked = 1;
});
The idea is to take manual control of the loading and inserting of the remote content received from /Stores/Create. I'm not set up to test this but give it a try.
You will need to get rid of/comment out the existing .on('showN.bs.modal') handler, and you might have to get rid of the href on the <a> tag that invokes the modal, not sure.
$('#modal-action-store').on('show.bs.modal', function (e) {
if (wasclicked == 1) {
// load the form, once it's done loading modify it as needed
$('#modal-action-store').find('.modal-content').load('/Stores/Create', function () {
$('#DistrictID').html('<option value='0'>-- Seleccione Distrito --</option>');
});
}
});
I have multiple input boxes with the attribute name="user[]"
When a button is clicked for a particular input I need to find out at what index of user was clicked.
I've tried a few method like .index(), .attr('name"), but I cant find out the index.
How is this possible?
<div>
<input type="hidden" name="user[]"> <!-- index 0 -->
<button class="btn btn-primary">
</div>
<div>
<input type="hidden" name="user[]"> <!-- index 1 -->
<button class="btn btn-primary">
</div>
<div>
<input type="hidden" name="user[]"> <!-- index 2 -->
<button class="btn btn-primary">
</div>
...
new div can be added by clicking a button.
This is used for a user invite form so there are no ids.
I need something like this
$('button').on('click', function() {
var index = $(this).parent().children('input').getTheIndex();
// where the index is defined by the use of []
});
jQuery's .index() finds the index of an element within the given collection.
So, to search among the name="user[]" inputs, you'll first need to find all of them:
var index = $(':text[name="user[]"]')...;
Then, you can determine the .index() of the current input among them:
var index = ...index(currentInput);
Example:
$('button').on('click', function() {
var allUsers = $('[name="user[]"]');
var user = $(this).siblings('[name="user[]"]');
var index = allUsers.index(user.get(0)); // get the native DOM node for the search
console.log(index); // 0, 1, ...
console.log(user.get(0) === allUsers.get(index)); // true
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<input type="hidden" name="user[]"> <!-- index 0 -->
<button class="btn btn-primary">Test</button>
</div>
<div>
<input type="hidden" name="user[]"> <!-- index 1 -->
<button class="btn btn-primary">Test</button>
</div>
<div>
<input type="hidden" name="user[]"> <!-- index 2 -->
<button class="btn btn-primary">Test</button>
</div>
If the buttons each relate to a specific hidden element, this will do it:
var $users = $("input[type=hidden]");
var $buttons = $(".btn-primary");
$buttons.on("click", function(){
// Get the index of the button, since it will match the
// index of the input
alert("Button index was: " + $buttons.index(this));
// Get the index of the hidden element that comes just before the
// button that was clicked:
alert("Hidden index was: " + $users.index(this.previousElementSibling));
});
Fiddle: https://jsfiddle.net/cvnwr89p/5/
By the way, you need to close your <button> elements.
I think you need to set data attribute of that input boxes to the something like data-user-id=42 so you can look for checked boxes and get their data attribute. If you want something like "index within all form elements" than you need something like document.getElementById("form").elements where you can look for you inputs...
You could do this:
$('.btn-primary').on('click', function() {
console.log($('.btn-primary').index($(this)))
});
This is what I have right now. I'm trying to add fields to the form dynamically using jQuery add() and append() method. But I want to remove the particular added field when the remove button is clicked.
<div class="col-md-12">
<h3>Added Description Fields</h3>
<div class="col-md-12" id="descFields">
</div>
</div>
JS
$(document).ready(function() {
console.log(descFields);
$('#addDesc').click(function(e) {
var descFields = $('#descFields');
var descLabel = $('#descLabel').val();
var large = '<div class="form-group" id="descField"><div class="input-group"><input type="text" class="form-control" placeholder="Enter Value For ' + descLabel + '" /><span class="input-group-btn"><button class="btn btn-danger" id="removeDesc" type="button">Remove</button></span></div>';
descFields.add(large).appendTo(descFields);
e.preventDefault();
});
$('#removeDesc').click(function(e) {
$(this).remove();
});
});
When the user click on the #removeDesc button , the the field that is added should be removed. I cannot figure out how to achieve this.
There are many ways of doing this, but the simpler for your problem is this one:
$(document).ready(function() {
console.log(descFields);
$('#addDesc').click(function(e) {
var descFields = $('#descFields');
var descLabel = $('#descLabel').val();
var large = '<div class="form-group" id="descField"><div class="input-group"><input type="text" class="form-control" placeholder="Enter Value For ' + descLabel + '" /><span class="input-group-btn"><button class="btn btn-danger" id="removeDesc" type="button">Remove</button></span></div>';
descFields.add(large).appendTo(descFields);
e.preventDefault();
});
$('#descFields').on('click', '#removeDesc', function(e) {
$(this).parents('.form-group').remove();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="descLabel"/>
<button id="addDesc">Add Desc</button>
<div class="col-md-12">
<h3>Added Description Fields</h3>
<div class="col-md-12" id="descFields">
</div>
</div>
Your problem is in the callback to delete the rows. When the document has finished loading you are trying to attach a click event to an object #removeDesc that is still not present in the DOM because it's created on the fly when the user clicks the #addDesc.
That's why you should use:
$('#descFields').on('click', '#removeDesc', function(e) {
$(this).parents('.form-group').remove();
});
As #vijayP suggested before you can use the on() to attach an event handler to the container where you'll be adding the object that is still not present in the DOM. Then you pass in the query selector as the second parameter to filter in execution time which of its children will trigger the event and execute the callback.
My additional trick is that I'm using .parents('.form-group') to select the div containing the group and remove all of the fields that were added instead of removing only the button.
Happy coding!
Add click event for remove button like follows:
$(document).on("click","#removeDesc",function(e) {
$(this).remove();
});
I have add clone (more than 3) and remove clone button. when i try to clone
<div class="data-add">
<div class="form-group" id="id1">
<label class="col-lg-2 control-label"> Image* : </label>
<div class="col-lg-10">
<input id="input-702" name="userfile[]" type="file"class="file-loading">
</div>
</div>
<div class="form-group clearfix" id="id2">
<label class="col-lg-2 control-label">option* :
</label>
<div class="col-lg-10">
<select name="option[]" autocomplete="off">
<option>name1</option>
<option>name2</option>
<option>name3</option>
</select>
</div>
</div>
</div>
<button class="add" type="button">Add Another </button>
<button class="remove" id="remove"> remove </button>
$(".add").click(function(){
$("#id1").clone().appendTo(".data-add");
$("#id2").clone().appendTo(".data-add");
});
It clone particular div happening proper. when i click remove its not working
(not able to remove)
$(".remove").click(function(){
$(this).closest("#id1").remove();
$(this).closest("#id2").remove();
});
i have tried this also
$(".remove").click(function(){
$(this).parents("#id1").remove();
$(this).parents("#id2").remove();
});
$(".remove").click(function(){
$("#id1").remove();
$("#id2").remove();
});
when i used like this it removing first clone(first id1 and id2). not removing current clone div
Change ID first of all, like below.
var newId = 10; // Sample ID To Append
var startID = ["id1_", id2_];
$(".add").click(function(){
var oldId = newId;
startID[0].replace(oldId, newId);
startID[1].replace(oldId, newId);
var newId++;
$("#id1").clone().attr('id', startID[0]).addClass("clonedDiv").appendTo(".data-add");
$("#id2").clone().attr('id', startID[1]).addClass("clonedDiv").appendTo(".data-add");
});
Then use the new ID or the common class .clonedDiv to remove them.
Elements having #id1 and #id2 are being added in the DOM dynamically, so you should use .on() function to bind your events e.g.
$(document).on('click', '.remove', function(){
$("#id1").remove();
$("#id2").remove();
});