Shift is not a function in javascript - javascript

I have multiple tables(with same structure)in my html. They are in tabs. I am creating tabs dynamically and i want to send those table data to the mysql database. So i wanted to get those data using javascript. I am correctly created TableData1,TableData2.... arrays using for loop. Problem is I cannot increment TableData here ('TableData'+i).shift(); . I am getting an error. I want to create TableData1.shift(),TableData2.shift().....
function myDataSendFunction(){
var i;
for(i = 1; i <= array_size; i++){
eval("var TableData"+i+"=[];");
$('#mytable'+i+ ' tr').each(function(row, tr){
('TableData'+i)[row]={
"colum1" : $(tr).find('td:eq(1)').text()
, "colum2" :$(tr).find('td:eq(2)').text()
, "colum3" : $(tr).find('td:eq(3)').text()
, "colum4" : $(tr).find('td:eq(4)').text()
, "colum5" : $(tr).find('td:eq(5)').text()
, "colum6" : $(tr).find('td:eq(6)').text()
, "colum7" : $(tr).find('td:eq(7)').text()
, "colum8" : $(tr).find('td:eq(8)').text()
}
});
('TableData'+i).shift();
}
}
I am getting this error.
Uncaught TypeError: ("TableData" + i).shift is not a function
at myDataSendFunction (<anonymous>:25:25)
at HTMLInputElement.onclick (create.php:1)

It's clear that you are very new to this, so I'm going to show you first and then explain second.
function myDataSendFunction(){
var i,
TableData = [];
for(i = 1; i <= array_size; i++){
TableData[i] = [];
$('#mytable' + i + ' tr').each(function(row, tr){
TableData[i][row]={
"colum1" : $(tr).find('td:eq(1)').text()
, "colum2" : $(tr).find('td:eq(2)').text()
, "colum3" : $(tr).find('td:eq(3)').text()
, "colum4" : $(tr).find('td:eq(4)').text()
, "colum5" : $(tr).find('td:eq(5)').text()
, "colum6" : $(tr).find('td:eq(6)').text()
, "colum7" : $(tr).find('td:eq(7)').text()
, "colum8" : $(tr).find('td:eq(8)').text()
};
});
TableData[i].shift();
}
}
Base on your comment:
what should i do then?? I tried with TableData array, then problem occurs in here TableData[i][row] with Uncaught TypeError: Cannot set property '0' of undefined
Your troubles revolve around setting properties on variables that haven't been defined. You must define TableData before attempting to assign a property.
Once TableData is "initialized" to an array (var TableData = []), you can set properties on TableData. But you cannot immediately set properties on properties of TableData. For example, you cannot jump directly to TableData[i][row]. You must first set TableData[i] to an array (TableData[i] = []), and then you can set TableData[i][row] to some value.
By trying to solve that problem with eval, you ran into a whole new world of problems. Try to avoid eval... it's a very complicated beast that tends to cause a lot of confusion and pain.
It may be helpful to review MDN's Working with objects documentation to better understand what's going on with JavaScript's array and objects.

Apparently your element selection is the mistake you have done. Without using a for loop by hard coding an array_size you could have easily
select all the tables at once using a common property like class. You will get an array with table objects.
Iterate the table objects array.
Inside the loop select all the rows of each table and put them into another loop to extract data and create the data array which you sends to the DB.
Find my sample implementation here.
Please do remember that when you're planning to use arrays, stick to the arrays rather than moving back and forth between strings and arrays. It will cause you problems like what you have already came across and unnecessary dirty code.

Related

issue with javascript set.has in lwc

I'm trying to use set.has() in lightning web components and it seems to be not working.
Below is the code snippet..
sStatusToVerify = 'Complete';
var setStatusVals = [...new Set(this.lstAllData.map(obj => obj.sStatus))];
console.log('setStatusVals : ',setStatusVals);
console.log('Contains?? : ' ,setStatusVals.has(sStatusToVerify));
setStatusVals consoles all the values and it contains "Complete". However, the next console is not printed at all. It should ideally print true. Not sure why this is not working.
What is wrong here?
The problem with your solution is , you are converting the set back to array by using the spread operator [... new Set()] and array does not has has method . Hence the issue
var sStatusToVerify = 'Complete';
var arr=[{sStatus:'Complete'},{sStatus:'Start'},{sStatus:'InProgress'}];
var setStatusVals = new Set(arr.map(obj => obj.sStatus));
console.log(setStatusVals.has(sStatusToVerify));

Array in javascript like php

Hello guys I'm trying to make a array in javascript like I can make in php. In php i can make a array like this and then insert in whatever index I like
$p = array();
$p["abcd"] = "James";
Now I want this functionality in js. Is it possible to do it in js
I have done something like this but this is throwing me an error
$.each( $('table[data-step-id=' + step_id +'] input[name^=actions]') , function(key , value){
debugger;
steps_actions_dates_assign[key]["action"].push(value.val());
});
this is the error
Uncaught TypeError: Cannot set property 'action' of undefined
MY QUESTION IS NOT A DUPLICATE
I'm not trying to access a php array in javascript but I'm trying to make a array in javascript like php(the way we do not have to worry about indexes the same way I should be able to add any index I want)
THIS IS ALL OF THE CODE
var steps_actions_dates_assign = new Array();
$.each($('.steps-table') , function (key , value){
debugger;
step_id = value.children[0].value;
steps_actions_dates_assign[key]["action"] = new Array();
$.each( $('table[data-step-id=' + step_id +'] input[name^=actions]') , function(key , value){
debugger;
steps_actions_dates_assign[key]["action"].push(value.val());
});
});
JavaScript arrays are designed for numeric indexes and hold ordered data.
Use objects to store properties with arbitrary names.
var p = {};
p["abcd"] = "James";
In JS, an array is a kind of object so it is possible to store arbitrary properties on it, but you will run into problems when you attempt to iterate over the array or pass it to functions such as JSON.stringify.
If you are using ES6 than Maps are another option.

JS: encapsulated foreach loop with arrays for JSON

I'm trying to get a foreach loop in a second one.
My code:
var results = data.d.results;
var boxes= [
"Nmb1",
"Nmb2",
"Nmb3",
"Nmb4",
"Nmb5",
];
boxes.forEach(function(n){
var boxesEach = results[0].n.results;
boxesEach.forEach(function(i){
$("input[value="+'"'+i+'"'+"]").attr('checked', true);
});
});
What I'm trying to do is to make for example "Nmb1" replacing the "n" which would make the following "output code":
var boxesEach = results[0].Nmb1.results;
It works if I just put the code like that but not with the loop.
Thanks for help and tips.
BTW: I'm getting the JSON via AJAX from a Sharepoint 2013 server (with the REST API).
You need to use it like an index. This is called the bracket notation (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Bracket_notation)
var boxesEach = results[0][n].results;
The one you have right now tries to use a Dot notation for which you'd need the actual property name (i.e. Nmb1) and not a variable which holds the property name.

Accessing a Dynamically Named array in jQuery/javascript

I wish to name an array according to the table row containing the button that was clicked.
I get the table row thus:
var rowNum = $(this).parent().parent().index();
Now, I wish to name the array and access it.
var arrayName = 'arrTR' + rowNum;
window[arrayName] = new Array();
window[arrayName]["First"] = "Bob";
window[arrayName]["Last"] = "Roberts";
window[arrayName]["email"] = "me#there.com";
//The array should be accessible as arrTR__
alert(arrTR1["Last"]);
The alert does not work, so I am doing something wrong.
How should I refactor the code to allow me to update and access the array?
jsFiddle
What you're doing with the dynamically named variables is essentially creating an array of those variables (one for each rowNum), but giving each of those array elements its own individual named variable.
There is a much better way to do this. Instead of generating a series of dynamically named variables, make a single array or an object. Then add an element or property for each of the dynamically named variables you were going to generate.
Your test code could look like this:
var arrTR = [];
var rowNum = 1;
arrTR[rowNum] = {
First: 'Bob',
Last: 'Roberts',
email: 'me#there.com'
};
alert( arrTR[1].Last );
Alternatively, you can do something with $.data as mentioned in Johan's answer. But if you do use plain JavaScript code, use a single array as described here instead of multiple dynamically named variables.
There are several reasons to do it this way. It's cleaner and easier to understand the code, it may be faster when there are large numbers of entries, and you don't have to pollute the global namespace at all. You can define the var arrTR = []; in any scope that's visible to the other code that uses it.
Arrays and objects are made for keeping track of lists of things, so use them.
There is nothing wrong with your code, and the only place it has error is the alert since it is not defined on the first click button
see this fiddle with a little update
if(rowNum === 1)
alert(arrTR1["Last"]);
else if(rowNum === 2)
alert(arrTR2["Last"]);
fiddle
How about something like this?
$('.getinfo').click(function() {
var result = $('table tr:gt(0)').map(function(k, v){
return {
firstName: $(v).find('.fname').val(),
lastName: $(v).find('.lname').val(),
email: $(v).find('.email').val(),
}
}).get();
//update to show how you use the jQuery cache:
//1. set the value (using the body tag in this example):
$('body').data({ result: result });
//2. fetch it somewhere else:
var res = $('body').data('result');
});
Not sure how you want to handle the first row. I skip in in this case. You can access each row by result[index].
As you might have noticed, this saves all rows for each click. If you want to use the clicked row only, use the this pointer.
http://jsfiddle.net/nwW4h/4/

Dynamically making a Javascript array from loop

I know there are a lot of questions about this, but I can't find the solution to my problem and have been on it for a while now. I have two sets of input fields with the same name, one for product codes, and one for product names. These input fields can be taken away and added to the DOM by the user so there can be multiple:
Here is what I have so far, although this saves it so there all the codes are in one array, and all the names in another:
var updatedContent = [];
var varCode = {};
var varName = {};
$('.productVariationWrap.edit input[name="varVariationCode[]"]')
.each(function(i, vali){
varCode[i] = $(this).val();
});
$('.productVariationWrap.edit input[name="varVariationName[]"]')
.each(function(i1, vali1){
varName[i1] = $(this).val();
});
updatedContent.push(varCode);
updatedContent.push(varName);
I am trying to get it so the name and code go into the same array. i.e. the code is the key of the K = V pair?
Basically so I can loop through a final array and have the code and associated name easily accessible.
I can do this in PHP quite easily but no luck in javascript.
EDIT
I want the array to look like:
[
[code1, name1],
[code2, name2],
[code3, name3]
];
So after I can do a loop and for each of the arrays inside the master array, I can do something with the key (code1 for example) and the associated value (name1 for example). Does this make sense? Its kind of like a multi-dimensional array, although some people may argue against the validity of that statement when it comes to Javascript.
I think it's better for you to create an object that way you can access the key/value pairs later without having to loop if you don't want to:
var $codes = $('.productVariationWrap.edit input[name="varVariationCode[]"]'),
$names = $('.productVariationWrap.edit input[name="varVariationName[]"]'),
updatedContent = {};
for (var i = 0, il = $codes.length; i < il; i++) {
updatedContent[$codes.get(i).value] = $names.get(i).value;
}
Now for example, updatedContent.code1 == name1, and you can loop through the object if you want:
for (var k in updatedContent) {
// k == code
// updatedContent[k] == name
}
Using two loops is probably not optimal. It would be better to use a single loop that collected all the items, whether code or name, and then assembled them together.
Another issue: your selectors look a little funny to me. You said that there can be multiple of these controls in the page, but it is not correct for controls to have duplicate names unless they are mutually exclusive radio buttons/checkboxes--unless each pair of inputs is inside its own ancestor <form>? More detail on this would help me provide a better answer.
And a note: in your code you instantiated the varCode and varName variables as objects {}, but then use them like arrays []. Is that what you intended? When I first answered you, i was distracted by the "final output should look like this array" and missed that you wanted key = value pairs in an object. If you really meant what you said about the final result being nested arrays, then, the smallest modification you could make to your code to make it work as is would look like this:
var updatedContent = [];
$('.productVariationWrap.edit input[name="varVariationCode[]"]')
.each(function(i, vali){
updatedContent[i] = [$(this).val()]; //make it an array
});
$('.productVariationWrap.edit input[name="varVariationName[]"]')
.each(function(i1, vali1){
updatedContent[i1].push($(this).val()); //push 2nd value into the array
});
But since you wanted your Code to be unique indexes into the Name values, then we need to use an object instead of an array, with the Code the key the the Name the value:
var updatedContent = {},
w = $('.productVariationWrap.edit'),
codes = w.find('input[name="varVariationCode[]"]'),
names = w.find('input[name="varVariationName[]"]');
for (var i = codes.length - 1; i >= 0; i -= 1) {
updatedContent[codes.get(i).val()] = names.get(i).val();
});
And please note that this will produce an object, and the notation will look like this:
{
'code1': 'name1',
'code2': 'name2',
'code3': 'name3'
};
Now you can use the updatedContent object like so:
var code;
for (code in updatedContent) {
console.log(code, updatedContent[code]); //each code and name pair
}
Last of all, it seems a little brittle to rely on the Code and Name inputs to be returned in the separate jQuery objects in the same order. Some way to be sure you are correlating the right Code with the right Name seems important to me--even if the way you're doing it now works correctly, who's to say a future revision to the page layout wouldn't break something? I simply prefer explicit correlation instead of relying on page element order, but you may not feel the need for such surety.
I don't like the way to solve it with two loops
var updatedContent = []
$('.productVariationWrap.edit').each(function(i, vali){
var $this = $(this)
, tuple = [$this.find('input[name="varVariationCode[]"]').val()
, $this.find('input[name="varVariationName[]"]').val()]
updatedContent.push(tuple)
});

Categories