I would like to ask for you help. I am currently having a problem in select2/jquery. I've been solving this for 1 day now.
Here is the scenario:
Inventory Table
I have a customer code and a customer name field(select2).
I can type on the customer code field, and once I selected a customer code, the customer name field will be automatically filled out.
The same with the customer name field, If I selected a customer name, the customer code field will be filled out.
Now, I already got it working. The problem is, I have a code that will automatically fill each field. But what happens is, it seems that if I change the customer name field, it will fill out the customer code field, and it will trigger again to change the customer name field, and it goes on and on. They keep on changing each other. Like a never ending loop.
My question is, how can I trigger it only once, so it would not continue in a loop.
If I change the customer code field, it would fill out the customer name field. Stop.
If I change the customer name field, it would fill out the customer code field. Stop.
Hoping for you guidance. Thank you everyone. Here is my code:
$('body').on('select2:select', '.select-customer-code', function (e) {
var data = e.params.data;
var customer_code = data.id;
var parent = $(this);
/** Load Ajax */
ajax_loader(baseUrl + 'merchandiser/inventory/manual/customer/info/fetch', {
customer_code: customer_code
}).done(function (response) {
var response = $.parseJSON(response);
var el = parent.parent().parent('tr').find('.select-customer-name');
/** Load select2 */
select2_loader_plain(el, customer_name_url);
el.select2('trigger', 'select', {
data: {
id: response.customer_code,
text: response.customer_name
}
});
});
});
$('body').on('select2:select', '.select-customer-name', function (e) {
var data = e.params.data;
var parent = $(this);
var el = parent.parent().parent('tr').find('.select-customer-code');
el.select2('trigger', 'select', {
data: {
id: data.id,
text: data.id
}
});
});
EDIT: (ADDED THE HTML MARKUP)
<table width="100%" class="table table-condensed">
<thead>
<tr>
<th><input type="checkbox"></th>
<th>#</th>
<th>Customer Code</th>
<th>Customer Name</th>
<th>Inventory Date</th>
<th>Material Code</th>
<th>Material Description</th>
<th>UOM</th>
<th>QTY</th>
<th>Batch</th>
<th>Reported By</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox"></td>
<td>1</td>
<td><select class="form-control form-select select-customer-code"></select></td>
<td><select class="form-control form-select select-customer-name"></select></td>
<td><input type="text" class="form-control"></td>
<td><input type="text" class="form-control"></td>
<td><input type="text" class="form-control"></td>
<td>
<select name="" id="" class="form-control">
<option value=""></option>
</select>
</td>
<td><input type="text" class="form-control"></td>
<td><input type="text" class="form-control"></td>
<td><input type="text" class="form-control"></td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>2</td>
<td><select class="form-control form-select select-customer-code"></select></td>
<td><select class="form-control form-select select-customer-name"></select></td>
<td><input type="text" class="form-control"></td>
<td><input type="text" class="form-control"></td>
<td><input type="text" class="form-control"></td>
<td>
<select name="" id="" class="form-control">
<option value=""></option>
</select>
</td>
<td><input type="text" class="form-control"></td>
<td><input type="text" class="form-control"></td>
<td><input type="text" class="form-control"></td>
</tr>
</tbody>
</table>
EDIT 2: SOLUTION (answered by Tom Jenkins)
var code_lock = false;
$('.select-customer-code').on('select2:select', function (e) {
var data = e.params.data;
var customer_code = data.id;
var customer_name = $('.select-customer-name');
if (!code_lock) {
/** Load Ajax */
ajax_loader(baseUrl + 'merchandiser/inventory/manual/customer/info/fetch', {
customer_code: customer_code
}).done(function (response) {
var response = $.parseJSON(response);
customer_name.select2('trigger', 'select', {
data: {
id: response.customer_code,
text: response.customer_name
}
});
});
}
});
$('.select-customer-name').on('select2:select', function (e) {
var data = e.params.data;
var parent = $(this);
var customer_code = $('.select-customer-code');
customer_code.select2('trigger', 'select', {
data: {
id: data.id,
text: data.id
}
});
code_lock = true;
setTimeout(function () {
code_lock = false;
}, 1000);
});
What if you were to add a global variable called recentlyChanged then before you make a change, you check to see if it was recently changed. If it was recently changed, you do not make the changes. If it was not recently changed, set the global variable to show it was recently changed, and use setTimeout to delay changing it back to not being recently changed. Does that make sense?
Related
I make a table in a form to enable user to submit several item in one time. I am able to use jquery to get the first row of the value input by user. But when they type in the value in the second row, it show error. I am pretty sure there is something wrong with the array that I am using. I have try 2 methods, both method work but it only takes the value from first row only.
<form>
<table>
<thead>
<tr>
<th>Item Code</th>
<th>Item Name</th>
<th>Status</th>
</tr>
</thead>
<tbody id="entrybody">
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
</tbody>
</table>
</form>
$(function() {
$.post("action.php", function(data) {
$("[name='title']").val(data.title);
$("[name='body']").val(data.body);
}, "json");
setInterval(function() {
var itemlist = new Array;
var count = 1;
var title = $("[name='title']").val();
var body = $("[name='body']").val();
itemlist[count - 1] = {};
$("#productbody tbody tr").each(function() {
var that = $(this);
if (that.find("[name='prd_code']").val().length !== 0) {
/*itemlist.push(code);
itemlist.push(name);
itemlist.push(cond);*/ //method 1
itemlist[count - 1].code = that.find("[name='prd_code']").val();
itemlist[count - 1].name = that.find("[name='prd_name']").val();
itemlist[count - 1].cond = that.find("[name='prd_cond']").val(); //method 2
count++;
}
});
console.log(itemlist);
}, 2000);
});
===== Console message (first row) =====
0:
code: "test_code1"
cond: "test_status1"
name: "test_name1"
I've changed the method of the event to a .change() for this example.
Then I've changed the following code:
var itemlist = new Array;
var title = $("[name='title']").val();
var body = $("[name='body']").val();
$("#productbody tbody tr").each(function(i) {
var that = $(this);
if (that.find("[name='prd_code']").val().length !== 0) {
itemlist[i] = {};
itemlist[i].code = that.find("[name='prd_code']").val();
itemlist[i].name = that.find("[name='prd_name']").val();
itemlist[i].cond = that.find("[name='prd_cond']").val(); //method 2
}
});
One problem was that you use this itemlist[count - 1] = {}; before your foreach statement. so you only created the first object.
Demo
$(function() {
$("#productbody tbody tr input").change(function() {
//setInterval(function() {
var itemlist = new Array;
var title = $("[name='title']").val();
var body = $("[name='body']").val();
$("#productbody tbody tr").each(function(i) {
var that = $(this);
if (that.find("[name='prd_code']").val().length !== 0) {
itemlist[i] = {};
itemlist[i].code = that.find("[name='prd_code']").val();
itemlist[i].name = that.find("[name='prd_name']").val();
itemlist[i].cond = that.find("[name='prd_cond']").val(); //method 2
}
});
console.log(itemlist);
});
//}, 2000);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<table id="productbody">
<thead>
<tr>
<th>Item Code</th>
<th>Item Name</th>
<th>Status</th>
</tr>
</thead>
<tbody id="entrybody">
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
</tbody>
</table>
</form>
As far as I understand you want to create an array of the values from all table cells in all rows. Here is a relative simple way to do this without JQuery.
document.addEventListener(`change`, handle);
function handle(evt) {
if (evt.target.name.startsWith(`prd_`)) {
// retrieve all rows
const values = [...document.querySelectorAll(`tbody tr`)]
// map to objects containing row number and values
.map(row => ({
row: row.rowIndex,
values: [...row.querySelectorAll(`[name^='prd_']`)]
.reduce( (acc, val) => ({...acc, [val.name]: val.value}), {})
}))
.filter(val => (val.values.prd_code || ``).trim().length > 0);
document.querySelector(`pre`).textContent = JSON.stringify(values, null, 2);
}
}
<table>
<thead>
<tr>
<th>Item Code</th>
<th>Item Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
</tbody>
</table>
<pre></pre>
I have a table which looks like below and i want to get all values inside the table including the value of text box and check box.
<div class="container-fluid">
<h1 class="h3 mb-4 text-gray-800"><?= $title; ?></h1>
<div class="container" style="text-align: left">
<table class="table table-sm" id="tbl">
<thead>
<tr>
<th>No</th>
<th>Checklist Item</th>
<th>Cheklist</th>
<th>Actual</th>
<th>Recomended</th>
</tr>
</thead>
<tbody>
<tr>
<td scope="row">1</td>
<td>Check and clean rubber roller cage</td>
<td><input type="checkbox" name="chek" id="check"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
<tr>
<td scope="row">2</td>
<td>Tension Rod all </td>
<td><input type="checkbox" name="chek" id="check"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
<tr>
<td scope="row">3</td>
<td>Delete all unnecessary file from system</td>
<td><input type="checkbox" name="chek" id="check"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
</table>
save
</div>
when i grab all value using this script i cant get value inside the text box and checkbox
$(document).on('click', '#save', function() {
var myRows = [];
var headersText = [];
var $headers = $("th");
// Loop through grabbing everything
var $rows = $("tbody tr").each(function(index) {
$cells = $(this).find("td");
myRows[index] = {};
$cells.each(function(cellIndex) {
// Set the header text
if (headersText[cellIndex] === undefined) {
headersText[cellIndex] = $($headers[cellIndex]).text();
}
// Update the row object with the header/cell combo
myRows[index][headersText[cellIndex]] = $(this).text();
});
});
var myObj = {
"Array": myRows
};
alert(JSON.stringify(myObj));
});
I want to convert it to JSON but the value of text box and check box not shows inside table. Kindly help me to resolve this issue.
Thank you in advance.
You can find the input and use .val() to get its value if the table cell's text is empty. Checkboxes and text inputs will need to be handled separately.
const text = $(this).text();
if(text){
myRows[index][headersText[cellIndex]] = text;
} else {
const input = $(this).find('input');
if(input.is(":checkbox")){
myRows[index][headersText[cellIndex]] = +input.prop('checked');
} else {
myRows[index][headersText[cellIndex]] = input.val();
}
}
I have a problem here that when I click copy row and I want to get the remaining qty per item, the result is not accurate.
So let's just say the item mouse has 100 qty, and I inputted new qty for 50. So the remaining should be 50. And when I copied the item mouse and inputted 40, so the remaining now is 10. Same goes for other items. This should be the expected output.
Current Situation
JSFIDDLE
$('.qty').on("keyup", function() {
var id = $(this).data('id');
var value = $(this).val();
var sum = 0;
$("#table_name .qty").filter(function(){
if ($(this).data("id") == id){
sum += parseFloat(value);
}
});
console.log(sum);
$('.remaining').val(sum);
});
Your overall logic is REALLY unclear. Here is an example that might help.
$(function() {
function refreshIndex($t) {
$('tbody tr', $t).each(function(i, el) {
var c = i + 1;
var select = $(this).find('td:eq(0)').text(c);
});
}
function copyRow(e) {
var self = $(e.target);
var row = self.closest("tr");
row.clone().appendTo(self.closest("tbody"));
refreshIndex($("#table_name"));
}
function updateItem(e) {
var self = $(e.target);
var row = self.closest("tr");
var p = parseInt(self.val());
var q = parseInt(row.find("td:eq(2) input").val());
$('.remaining', row).val(q - p);
}
$("#table_name tbody").on("keyup", '.price', updateItem);
$("#table_name tbody").on('click', '.copy', copyRow);
});
#table_name tr td input {
width: 4em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table_name">
<thead>
<tr>
<th>No</th>
<th>Item</th>
<th>Total</th>
<th>Qnty</th>
<th>Action</th>
<th>Remaing</th>
</tr>
</thead>
<tbody>
<tr class="trs" id="tr-1">
<td>1</td>
<td>Mouse</td>
<td><input type="text" value="100" readonly></td>
<td><input type="text" class="price" data-id="79"></td>
<td><button class="copy" id="copy-1">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-2">
<td>2</td>
<td>Keyboard</td>
<td><input type="text" value="20" readonly></td>
<td><input type="text" class="price" data-id="80"></td>
<td><button class="copy" id="copy-2">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-3">
<td>3</td>
<td>Monitor</td>
<td><input type="text" value="50" readonly></td>
<td><input type="text" class="price" data-id="81"></td>
<td><button class="copy" id="copy-3">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
</tbody>
</table>
When I enter 40 under Price, 60 appears as the difference between the Quantity and the Amount entered.
When Copy is clicked, a new row is appended, and functionality is binded to it already due to use of .on().
Hope that helps.
Basically you can use the data-id attribute to target the rows you actually want to update.
var clone_controll = function(num) {
//Needed to mod this so add rows have the event handler
$('#table_name').on("keyup", ".qty", function() {
var id = $(this).data('id');
var value = $(this).val();
var sum = 0;
//Filter is the wrong choice here - it is designed to filter objects
/*$("#table_name .qty").filter(function(){
if ($(this).data("id") == id){
//I think this logic is incorrect as well
//You are only getting the value from the
//field you are typing in
sum += parseFloat(value);
}
});*/
/*Use a better selector with each()*/
$("#table_name [data-id=" + id +"]").each(function(){
//In this context "this" is the item iterated in "each"
sum += parseFloat($(this).val());
console.log(sum);
});
console.log("Final: " + sum);
//Here is your problem, this updates All "remaining fields
//$('.remaining').val(sum);
//All rows contiaining this data id
var relevantRows = $("[data-id=" + id + "]").closest("tr");
//Update the "remaining fields in those rows
$(relevantRows).find(".remaining").val(sum);
});
}
clone_controll();
var $tableBody = $('#table_name').find("tbody");
clickEvent();
function clickEvent(){
$tableBody.find('.copy').off('click').on('click',function() {
$trLast = $(this).closest('tr'),
$trNew = $trLast.clone();
$trLast.after($trNew);
clickEvent();
clone_controll();
});
function refresh_index(){
$('#table_name > tbody > tr').each(function (i) {
i++;
var select = $(this).find('td').eq(0).text(i);
});
}
refresh_index();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<table id="table_name">
<thead>
<tr>
<th>No</th>
<th>Item</th>
<th>Qty</th>
<th>Your Qty</th>
<th>Action</th>
<th>Remaing per item(not per row)</th>
</tr>
</thead>
<tbody>
<tr class="trs" id="tr-1">
<td>1</td>
<td>Mouse</td>
<td><input type="text" value="100" readonly></td>
<td><input type="text" class="qty" data-id="79"></td>
<td><button class="copy" id="copy-1">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-2">
<td>2</td>
<td>Keyboard</td>
<td><input type="text" value="20" readonly></td>
<td><input type="text" class="qty" data-id="80"></td>
<td><button class="copy" id="copy-2">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-3">
<td>3</td>
<td>Monitor</td>
<td><input type="text" value="50" readonly></td>
<td><input type="text" class="qty" data-id="81"></td>
<td><button class="copy" id="copy-3">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
</tbody>
</table>
Your logic is still pretty unclear, but hopefully this gets you moving in the right direction.
I have a table of movies and I am using ng-repeat to display the rows. But each column shows the movie variable (like name, director, actor, year..) and one of then is the genre but the movie can have multiple genres. So, I am using a select to do this.
The problem is, my select just don't show up in the screen! I don't know if this is a angular problem or I am doing something wrong..
Here is my table:
<div class="container" style="margin-top: 30px; min-width: 90%" ng-controller="adminController">
<table class="table table-hover">
<thead>
<tr>
<th>
<h2>Filme</h2>
</th>
<th>
<h2>Ano</h2>
</th>
<th>
<h2>Diretor</h2>
</th>
<th>
<h2>Ator/Atriz</h2>
</th>
<th>
<h2>Pontuação</h2>
</th>
<th>
<h2>Generos</h2>
</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr>
<td><input class="form-control" ng-model="novoFilme.nome" placeholder="Nome do filme"/></td>
<td><input class="form-control" ng-model="novoFilme.ano" placeholder="Ano do filme"/></td>
<td><input class="form-control" ng-model="novoFilme.diretor" placeholder="Diretor do filme"/></td>
<td><input class="form-control" ng-model="novoFilme.ator" placeholder="Ator/atriz do filme"/></td>
<td><input class="form-control" ng-model="novoFilme.pontuacao" placeholder="Pontuação do filme"/></td>
<td>
<select class="selectpicker" title="Nenhum selecionado" ng-model="novoFilme.generos" ng-options="genero.value as genero.nome for genero in generos" multiple>
</select>
</td>
<td style="text-align: right"><button class="btn btn-primary" ng-click="addFilme()">Adicionar Filme</button></td>
</tr>
<tr ng-repeat="filme in filmes">
<td><input class="form-control" ng-model="filme.nome"/></td>
<td><input class="form-control" ng-model="filme.ano"/></td>
<td><input class="form-control" ng-model="filme.diretor"/></td>
<td><input class="form-control" ng-model="filme.ator"/></td>
<td><input class="form-control" ng-model="filme.pontuacao"/></td>
<td>
<select class="selectpicker" title="Nenhum selecionado" ng-options="genero.value as genero.nome for genero in generos" multiple>
</select>
</td>
<td style="text-align: right"><button class="btn btn-danger" ng-click="remove(filme._id)">Remover</button></td>
</tr>
</tbody>
</table>
</div>
Here is my controller:
app.controller('adminController', function ($scope, $http) {
$scope.generos = [
{
nome: "Comédia",
value: "Comédia"
},
{
nome: "Comédia Romântica",
value: "Comédia Romântica"
},
{
nome: "Drama",
value: "Drama"
},
{
nome: "Ação",
value: "Ação"
},
{
nome: "Policial",
value: "Policial"
},
{
nome: "Suspense",
value: "Suspense"
},
{
nome: "Terror",
value: "Terror"
}
];
var atualizar = function () {
$http.get('/filmes').success(function (response) {
$scope.filmes = response;
$scope.novoFilme = "";
});
};
atualizar();
$scope.addFilme = function () {
$http.post('/filmes', $scope.novoFilme).success(function (response) {
atualizar();
});
};
$scope.remove = function (id) {
$http.delete('/filmes/' + id).success(function (response) {
atualizar();
});
};
$scope.save = function () {
for (i = 0; i < $scope.filmes.length; i++) {
$http.put('/filmes/' + $scope.filmes[i]._id, $scope.filmes[i]).success(function (response) {
atualizar();
});
}
};
});
Anyone knows how to fix it or any ideas how to do this in a different way?
Edit:
Here is the screen shot:
http://imgur.com/a/bXgBK
Well, ngOptions requires ngModel directive, so you have to use it in your <select> tag.
If you look at your console (pressing F12) you'll see this error:
Controller 'ngModel', required by directive 'ngOptions', can't be
found!
So, Instead of:
<select class="selectpicker" title="Nenhum selecionado"
ng-options="genero.value as genero.nome for genero in generos" multiple>
Use:
<select ng-model="genero" class="selectpicker" title="Nenhum selecionado"
ng-options="genero.value as genero.nome for genero in generos" multiple>
Tip: Always look at your console (F12) to see the errors when something went wrong.
I found that the problem is just the select class, in this case class="selectpicker", I don't know why this is causing issue, but if you remove this class will work fine.
Just to know, this class is a class from Silvio Moreto bootstrap select that you can find in the link below.
https://silviomoreto.github.io/bootstrap-select/
I am looking for a javascript plugin that will let users create MySQL tables using a very basic HTML interface. Ideally a CREATE statement would result from the HTML table. Does anyone know of such a script?
to my knowledge there is not a jquery plugin that will allow you to 'create' database tables, regardless you would still have to use some server side code to handle the actual SQL etc. it is not too difficult to create something yourself, i knocked together this which i think is the kinda thing your looking for. note: this is not a full implementation :P just an idea, basically create the table using html, parse it to json, then send it to the server to deal with it.
initial html 'template':
<table id="table_designer">
<tr class="table_name">
<td><input type="text" placeholder="table name" /></td>
</tr>
<tr class="field_name">
<td>name</td>
<td><input type="text" /></td>
</tr>
<tr class="type">
<td>type</td>
<td><select>
<option>int</option>
<option>varchar</option>
<option>date</option>
</select></td>
</tr>
<tr class="primary_key">
<td>primary key</td>
<td><input type="checkbox" /></td>
</tr>
<tr class="relationship">
<td>related type</td>
<td><select>
<option>none</option>
<option>one to many</option>
<option>many to one</option>
<option>many to many</option>
</select></td>
</tr>
<tr class="related_table">
<td>related table</td>
<td><input type="text" /></td>
</tr>
<tr class="related_field">
<td>related field</td>
<td><input type="text" /></td>
</tr>
<tr class="controls">
<td><button id="save">save</button></td>
<td>
<button id="delete">delete</button>
<button id="add">add</button>
</td>
</tr>
</table>
some jquery to handle the 'actions'
/* parses table as json and sends to server */
$('#save').click(function() {
var json= {};
$('#table_designer tr').each(function(){
var $t = $(this),
prop = $t.attr('class');
json[prop] = [];
$t.children('td').each(function() {
json[prop].push($(this).children().first().val());
});
});
alert(JSON.stringify(json, null, " "));
/* send the data to the server
$.post('www.mysite.com', json, function(d, t, j)
{ alert('success'); });
*/
});
/* deletes parent column */
$('#delete').click(function() {
var $t = $(this),
pos = $t.parents('td').index() + 1;
$('#table_designer tr').each(function(){
$(this).children('td:nth-child(' + pos +')').remove();
});
});
/* adds a new field */
$('#add').click(function() {
var $t = $(this),
pos = $t.parents('td').index() + 1;
$('#table_designer tr').each(function(){
var clone = $(this).children('td').last().clone(true);
clone.children('input').val('');
$(this).children('td:nth-child(' + pos +')').after(clone);
});
});