Form values are overwritten after change - javascript

I have a form that shows up when each row in a table is double clicked. The values of this form can be updated and the form should be submitted with all row changes. But each time I double click on a row and edit the values of that form for that row, the previous values I had changed get overwritten. In order to work around this, I tried adding all the changes to a map with the row id as the key and the values of the form as the value. But the form still won't update with the new values. Here is a fiddle to demonstrate what I mean:
https://jsfiddle.net/4fr3edk7/2/
If I double click on the row that says "Adam Smith" and change that name to John Doe, when I double click on the second row and then double Click on "Adam Smith" again, it should say "John" on the first textbox and "Doe" on the second one. But the new value never seems to save.
This code snippet loops through each key, then loops through each value of that key:
for(var i = 0; i<key.length; i++){
var getval = globalchanges[key[i]];
for(var k=0; k<getval.length; k++){
$("#input1").val(getval[0]);
$("#input2").val(getval[1]);
}
}
How can I get the new changes to save? (The table rows don't have to show the changes, just the textbox values). Any help would be appreciated.

First, as mentioned by #Taplar you are binding the click event multiple times. Your approach is close enough, the idea of storing the changes is valid. You should have 2 functions, store the changes on button click and the second one to retrieve the changes by id.
Updated Fiddle
This function will get the values of the form and will store in on a global object
function setMap(id){
var firstrow = $("#input1").val();
var secondrow = $("#input2").val();
globalchanges[id] = [firstrow,secondrow];
}
This other function will check if the global object has values for the passed id, if not, it will use the values on the row
function getMap(id, tr){
if(globalchanges[id] != undefined && globalchanges[id].length == 2){
$("#input1").val(globalchanges[id][0]);
$("#input2").val(globalchanges[id][1]);
}
else{
$("#input1").val($(tr).find('td').eq(1).text());
$("#input2").val($(tr).find('td').eq(2).text());
}
}
Please note there are also changes on the dbclick and click events, they should be separated
$("#table tr").dblclick(function(){
$("#txtbox-wrapper").css({"display" : "block"});
var id = $(this).find('td').eq(0).text();
$('#id').val(id);
getMap(id,this);
});
$("#savebtn").click(function(){
var id = $('#id').val();
setMap(id);
});
And that we added and additional input to store the id on the form.

You are going to need to rethink your logic because of this part
$("#table tr").dblclick(function(){
$("#txtbox-wrapper").css({"display" : "block"});
var id = $(this).find('td').eq(0).text();
$("#input1").val($(this).find('td').eq(1).text());
$("#input2").val($(this).find('td').eq(2).text());
$("#savebtn").click(function(){
addToMap(id);
});
});
-Every time- you double click a table row you are adding a new click binding to the savebtn element. This means if you double click both rows, when you click that button it will execute addToMap for both ids. You may have other issues with your logic relying on only two other inputs for multiple rows, but this double/triple/+ binding is going to bite you.

There are few changes required in your logic as well as implementation.
1: Do not bind save event inside row click.
2: You are selecting the value in row double click event from td element. You need to update this element to keep your logic working
3: Keep track of which row is getting updated.
Updated Code
var globalchanges = {};
var rowSelected = null;
$("#table tr").dblclick(function() {
$("#txtbox-wrapper").css({
"display": "block"
});
rowSelected = $(this).find('td').eq(0).text();
$("#input1").val($(this).find('td').eq(1).text());
$("#input2").val($(this).find('td').eq(2).text());
});
$("#savebtn").click(function() {
addToMap(rowSelected);
});
function addToMap(row) {
var array = [];
var changes = {};
var firstrow = $("#input1").val();
var secondrow = $("#input2").val();
array.push(firstrow, secondrow);
globalchanges[row] = array;
makeChanges(row);
}
function makeChanges(row) {
var key = Object.keys(globalchanges);
console.log(key);
$("#table tr td").each(function(k, v) {
if ($(v).text() == key) {
$(v).next().html(globalchanges[row][0]);
$(v).next().next().html(globalchanges[row][1]);
globalchanges = {};
}
});
}
Working fiddle : https://jsfiddle.net/yudLxsgu/

Related

Multiple input and multiple output with onclick eventlistener in javascript

Want to ask :
For example , i have multiple button and when i click on anyone, the value will be shown at the result textbox and the input textbox will back to 0 , need help on check my code :
document.getElementById("plusthevalue").addEventListener('click',function plus()
{
var inputvalue = document.getElementById("Input");
var resultvalue = document.getElementById("Result");
document.write("Result").value = inputvalue + resultvalue;
document.write("Input").value ="0";
});
and, if i want to write a single statement that can include all the button and will display the output depend on the button, how would the code will be?
p/s: i know i can hardwork until i code function for every button but that would be very messy , i want to include all :(
You can assign all your buttons a certain class, then use document.querySelectorAll('.myclass') to grab all of them. Then you can loop through the results to add the event listener to each of them.
Example:
var myButtons = document.querySelectorAll('.myclass');
for (i = 0; i < myButtons.length; ++i) {
myButtons[i].addEventListener('click', function(e) {
// Do stuff
}
}
See https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll for more info about querySelectorAll.

Kendo grid - get current editing row

How do you get the current row that's been edited even when it's not selected? I have a batch enabled Kendo grid that is navigatable. My goal is to manually edit data in a column using the dataItem.set() method. However, when you add a row it does not get selected automatically. Hence, vm.testGrid.dataItem(vm.testGrid.select()) cannot be used.
vm.testGrid.dataSource.get(e.model.get("Id")) gets the newly added row, but if multiple rows were added before saving, it will always get the first added row ("Id" is set to auto increment and is automatically generated by the database server, therefore all newly created rows will initially have 0 before saving).
vm.onEdit = function (e) {
$('input.k-input.k-textbox').blur(function (f) {
//var data = vm.testGrid.dataItem(vm.testGrid.select());
var data = vm.testGrid.dataSource.get(e.model.get("Id")); // will always get the firstly added row
data.set("LookupCol", "1000");
}
});
Is there a better solution to get the row that's been currently edited? Or is there a better way to edit the current row?
The following will give you the data item associated with the current cell:
var dataItem = grid.dataItem(grid.current().closest("tr"));
// You can then set properties as you want.
dataItem.set("field1", "foo");
dataItem.set("field2", "bar");
I used the JQuery closest() function:
vm.onEdit = function (e) {
$('input.k-input.k-textbox').blur(function (f) {
var data = vm.testGrid.dataItem($(e.container).closest("tr"));
data.set("LookupCol", "1000");
}
});
You can also write an extension for the grid, e.g. like this
// extend the grid
kendo.ui.Grid.fn.getCurrentDataItem = function() {
var that = this, current = that.current(), dataItem = null;
if (current) {
dataItem = that.dataItem(current.closest('tr'));
}
return dataItem;
}
JSFiddle example

javascript editable table does not work properly

I am using the following code to make a html table editable (this code is obtained from an online tutorial link: http://mrbool.com/how-to-create-an-editable-html-table-with-jquery/27425).
$("td").dblclick(function () {
//Obtain and record the value in the cell being edited. This value will be used later
var OriginalContent = $(this).text();
//Addition of class cellEditing the cell in which the user has double-clicked
$(this).addClass("cellEditing");
//Inserting an input in the cell containing the value that was originally on this.
$(this).html("<input type='text' value='" + OriginalContent + "' />");
//directing the focus (cursor) to the input that was just created, so that the user does not need to click on it again.
$(this).children().first().focus();
//the opening and closing function that handles the keypress event of the input.
//A reserved word this refers to the cell that was clicked.
//We use the functions first and children to get the first child element of the cell, ie the input.
$(this).children().first().keypress(function (e) {
//check if the pressed key is the Enter key
if (e.which == 13) {
var newContent = $(this).val();
$(this).parent().text(newContent);
$(this).parent().removeClass("cellEditing");
}
});
$(this).children().first().blur(function(){
$(this).parent().text(OriginalContent);
$(this).parent().removeClass("cellEditing");
});
});
It seems to work fine. Then I am using the following function to read the contents of the table and create a json representation:
function showRefTable(){
var headers = [];
var objects = [];
var headerRow = $('#dataTable thead tr');
var rows = $('#dataTable tbody tr');
headerRow.find('th').each(function(){
headers.push($(this).text());
});
for (var i=0; i<rows.length; i++){
var row = rows.eq(i);
var object = new Object();
for (var j=0; j<row.find('td').length; j++){
object[headers[j]] = row.find('td').eq(j).text();
}
objects.push(object);
}
var json = JSON.stringify(objects);
alert(json);
}
This function is used as a callback to an onclick event.
The problem is that the function used to read the table contents shows the original contents even if I make an edit (show page source shows the original content).
Thanks
It's really bad to read table contents from .text(). You will not be able to use any formatting for numbers and many other problems. You'd better of keeping table contents in standalone datasourse object and redrawing table from it every time when user changes values.
I would advise using kendo grid - it's powerfull, reliable js table.
EDIT: your function does not work, becuse you said you call it as callback to onclick event. So you read contents of the table before they actually changed.
You should read contents when they are saved. In your case, try calling you function when user saves the input (presses Enter)
if (e.which == 13) {
var newContent = $(this).val();
$(this).parent().text(newContent);
$(this).parent().removeClass("cellEditing");
//Now, when content is changed, call your function
showRefTable();
}

Recursive IDs and duplicating form elements

I have the following fiddle:
http://jsfiddle.net/XpAk5/63/
The IDs increment appropriately. For the first instance. The issue is when I try to add a sport, while it duplicates, it doesn't duplicate correctly. The buttons to add are not creating themselves correctly. For instance, if I choose a sport, then fill in a position, and add another position, that's all fine (for the first instance). But when I click to add another sport, it shows 2 positions right away, and the buttons aren't duplicating correctly. I think the error is in my HTML, but not sure. Here is the JS I am using to duplicate the sport:
$('#addSport').click(function(){
//increment the value of our counter
$('#kpSport').val(Number($('#kpSport').val()) + 1);
//clone the first .item element
var newItem = $('div.kpSports').first().clone();
//recursively set our id, name, and for attributes properly
childRecursive(newItem,
// Remember, the recursive function expects to be able to pass in
// one parameter, the element.
function(e){
setCloneAttr(e, $('#kpSport').val());
});
// Clear the values recursively
childRecursive(newItem,
function(e){
clearCloneValues(e);
});
Hoping someone has an idea, perhaps I've just got my HTML elements in the wrong order? Thank you for your help! I'm hoping the fiddle is more helpful than just pasting a bunch of code here in the message.
The problem is in your clearCloneValues function. It doesn't differentiate between buttons and other for elements that you do want to clear.
Change it to:
// Sets an element's value to ''
function clearCloneValues(element){
if (element.attr('value') !== undefined && element.attr('type') !== 'button'){
element.val('');
}
}
As #PHPglue pointed out in the comments above, when new positions are added, they are incorrectly replicated (I'm assuming here) to the newly cloned for
There is a similar problem with the add years functionality.
A quick fix would be to initialize a variable with a clone of the original form fields:
var $template = $('div.kpSports').first().clone();
Then change your addSport handler to:
$('#addSport').click(function () {
//increment the value of our counter
$('#kpSport').val(Number($('#kpSport').val()) + 1);
//clone the first .item element
var newItem = $template.clone();
…
});
However, there are no event bindings for the new buttons, so that functionality is still missing for any new set of form elements.
Demo fiddle
Using even a simple, naive string based templates the code can be simplified greatly. Linked is an untested fiddle that shows how it might be done using this approach.
Demo fiddle
The code was simplified to the following:
function getClone(idx) {
var $retVal = $(templates.sport.replace(/\{\{1\}\}/g, idx));
$retVal.find('.jsPositions').append(getItemClone(idx, 0));
$retVal.find('.advtrain').append(getTrainingClone(idx, 0));
return $retVal;
}
function getItemClone(setIdx, itemIdx) {
var retVal = itemTemplate.replace(/\{\{1\}\}/g, setIdx).replace(/\{\{2\}\}/g, itemIdx);
return $(retVal);
}
function getTrainingClone(setIdx, trainingIdx) {
var retVal = trainingTemplate.replace(/\{\{1\}\}/g, setIdx).replace(/\{\{2\}\}/g, trainingIdx);
return $(retVal);
}
$('#kpSportPlayed').on('click', '.jsAddPosition', function() {
var $container = $(this).closest('.kpSports');
var containerIdx = $container.attr('data_idx');
var itemIdx = $container.find('.item').length;
$container.find('.jsPositions').append(getItemClone(containerIdx, itemIdx));
});
$('#kpSportPlayed').on('click', '.jsAddTraining', function() {
var $container = $(this).closest('.kpSports');
var containerIdx = $container.attr('data_idx');
var trainIdx = $container.find('.advtrain > div').length;
$container.find('.advtrain').append(getTrainingClone(containerIdx, trainIdx));
});
$('#addSport').click(function () {
var idx = $('.kpSports').length;
var newItem = getClone(idx);
newItem.appendTo($('#kpSportPlayed'));
});

JQuery DataTables How to get selected rows from table when we using paging?

For example I selected (checked) 2 rows from second page than go to first page and select 3 rows. I want get information from 5 selected rows when I stay at first page.
$('tr.row_selected') - not working
Thanks.
Upd.
I created handler somthing like this:
$('#example').find('tr td.sel-checkbox').live("click", function () {
/*code here*/
});
But right now when click event is hadle the row from table is hidding. I think it may be sorting or grouping operation of DataTables. Any idea what I must do with this?
When a checkbox gets selected, store the row information you want in a global object as a Key-Value pair
I don't remember specifically how i did it before but the syntax was something like
$('input[type=checkbox]').click(function()
{
var row = $(this).parent(); //this or something like it, you want the TR element, it's just a matter of how far up you need to go
var columns = row.children(); //these are the td elements
var id = columns[0].val(); //since these are TDs, you may need to go down another element to get to the actual value
if (!this.checked) //becomes checked (not sure may be the other way around, don't remember when this event will get fired)
{
var val1 = columns[1].val();
var val2 = columns[2].val();
myCheckValues[id] =[val1,val2]; //Add the data to your global object which should be declared on document ready
}
else delete myCheckValues[id];
});
When you submit, get the selected rows from your object:
for (var i = 0; i < myCheckValues.length; i++)
...
Sorry, haven't done JS in a long time so code as is might not work but you get the idea.
$('#example').find('tr td.sel-checkbox').live("click", function () {
var data = oTable.fnGetData(this);
// get key and data value from data object
var isSelected = $(this).hasClass('row_selected');
if(isSelected) {
myCheckValues[key] = value;
checkedCount++;
} else {
delete myCheckValues[key];
checkedCount--;
}
});
.....
On submit
if(checkedCount > 0) {
for(var ArrVal in myCheckValues) {
var values = myCheckValues[ArrVal]; // manipulate with checked rows values data
}
}

Categories

Resources