Push an object to array, obejct overwritting the previos one - javascript

I am trying to push the object resultOBJ to the array resultArray
when the button "Добавить обозначение" is clicked.
first object has been sent well, the data is the same what I am looking for, but when I push another object the second object is rewriting the previous one, the third object is rewriting the first and the second and so on.
here is my code. Please, tell me what I am doing wrong.
Thanks in advance.
var color = {red:"#ff0000",purple:"#990099",green:"#33cc33",yellow:"#ffff00",blue:"#0000ff",orange:"#ff8000",pink:"#ff0080",
skyblue:"#00ffff",black:"#000000",gray:"#808080",brown:"#4d1f00"};
var diams = ["60","65","68","69","70","75","76","80","81","82","85","90"];
//show hidden elements
$(document).ready(function(){
$("#addRowDDL").click(function(){
$("#DDL,#deleteRowDDl,#useIt").fadeIn("slow");
});
});
var resultOBJ=new Object();
var resultArray = new Array();
var finalobj = {} ;
var obj = new Object();
function addDropDownLists(){
var myObject = $("#htmltoget").children().clone();
$("#DDL").append(myObject);
$.each(diams,function(key,value){
myObject.find(".chooseDiams").append($("<option></option>").attr("value",key)
.text(value));
});
$.each(color,function(key,value){
myObject.find(".chooseColor").append($("<option></option>").attr("value",key)
.text(key));
});
myObject.find(".chooseColor").change(function(){
displayColors(this);
});
myObject.find(".chooseDiams").change(function(){
displayDiams(this);
});
resultArray.push(obj);
}//End of addDropDownLists function
function displayColors(param){
var colorValues = $(param).val();
resultOBJ.color=colorValues;
}
function displayDiams(param){
var diamsValues = $(param).val() || [];
resultOBJ.diams=diamsValues;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="htmltoget" style="display: none;">
<div class="DDL-Con">
<div class="diams">
<p>Диаметр</p>
<select class="chooseDiams" multiple>
<option selected hidden> Выбрать Диаметр</option>
</select>
</div>
<div class="color">
<p>Цвет</p>
<select class="chooseColor">
<option selected hidden>Выбрать Цвет</option>
</select>
</div>
</div>
</div>
<button type="button" id="addRowDDL" onclick="addDropDownLists()" style="margin-bottom: 20px;">Добавить обозначение</button>
<div id="bigwrapper">
<div id="DDL">
</div>
</div>
</body>

Having a hard time telling what you're trying to accomplish but you push obj which is empty and should be giving you an array of empty objects.
Also, you need to create a new object for each call of addDropDownLists() otherwise you are just passing a reference and the changes will effect every object in the array.
//show hidden elements
$(document).ready(function(){
$("#addRowDDL").click(function(){
$("#DDL,#deleteRowDDl,#useIt").fadeIn("slow");
addDropDownLists();
});
});
var resultArray = new Array();
function addDropDownLists(){
var resultOBJ=new Object();
var myObject = $("#htmltoget").children().clone();
$("#DDL").append(myObject);
$.each(diams,function(key,value){
myObject.find(".chooseDiams").append($("<option></option>").attr("value",key)
.text(value));
});
$.each(color,function(key,value){
myObject.find(".chooseColor").append($("<option></option>").attr("value",key)
.text(key));
});
myObject.find(".chooseColor").change(function(){
resultOBJ.color = $(this).val();
});
myObject.find(".chooseDiams").change(function(){
resultOBJ.diams = $(this).val() || [];
});
resultArray.push(resultOBJ);
console.log(JSON.stringify(resultArray));
}//End of addDropDownLists function
This setup does insert an empty object into the array the first time the button is clicked, or if there is no change. Not sure what you're trying to accomplish though so I left it as is.
Demo: https://jsfiddle.net/3p37znq1/2/

You don't push resultOBJ, you push obj which is always empty as you don't do anything with it after initialization.
When you push obj each time you just push a reference to the same instance instead of creating a new one. Any change to obj will affect all items in resultArray.
In change handler you always update the same instance of resultOBJ and this update always overwrites previous change. Actually, the values in this object mean "last selected color anywhere" and "last selected diam anywhere".
Something like this should work:
var resultArray = [];
function renderOption(value, name) {
var option = document.createElement("option");
option.value = value;
option.innerHTML = undefined === name ? value : name;
return option;
}
function updateResult(index) {
var item = resultArray[index],
node = document.querySelector("#DDL").childNodes.item(index);
item.diam = node.querySelector(".chooseDiams").value;
item.color = node.querySelector(".chooseColor").value;
}
function addDropDownLists() {
var container = document.querySelector("#DDL"),
index = resultArray.length,
changeHandler = updateResult.bind(null, index),
tpl = document.querySelector(".DDL-Con"),
node = tpl.cloneNode(true),
list, key, len
;
list = node.querySelector(".chooseDiams");
for (key = 0, len = diams.length; key < len; key++) {
list.appendChild(renderOption(diams[key]));
}
list.onchange = changeHandler;
list = node.querySelector(".chooseColor");
for (key in color) {
list.appendChild(renderOption(key, color[key]));
}
list.onchange = changeHandler;
container.appendChild(node);
resultArray.push({
diam: null,
color: null
});
updateResult(index);
}
PS: Sorry, I see you use jQuery... I'm too lazy to remember it's API. Haven't used it for a long time. Hope, you'll catch the main idea.
PPS: if you plan to delete items, maybe it's better to bind the whole node and search for it's index via isSameNode() method. Bound indexes will become invalid after removing item, they will shift.

Related

How to Push only one object and update it into Array using JavaScript?

I am creating simple App using Vanilla JavaScript, I have some issue, Let's explain my problem,In the beginning i have empty array, I want to push some values from Input field, and it's works fine, but i want to push only one object into arrOfObj:[], that means i want replace old value by new value, without changing the length.
var arrOfObj = [];
function pushObject() {
var inputVal = document.getElementById('mainInput').value;
arrOfObj.push({ id: 1, value: inputVal });
console.log(arrOfObj);
}
<button onclick="pushObject()">click</button>
<input type="text" id="mainInput">
I think instead of using push, you can directly replace the first index with your new object
var arrOfObj = [];
function pushObject(){
var inputVal = document.getElementById('mainInput').value
//replace the first value of array
arrOfObj[0] = {'id':1, 'value':inputVal};
console.log(arrOfObj)
}
<button onclick="pushObject()">click</button>
<input type="text" id="mainInput">
You can achieve this by simply updating the 0th element of your array if there is one.
var arrOfObj = [];
function pushObject(){
var inputVal = document.getElementById('mainInput').value
if (arrOfObj[0]) {
arrOfObj[0].value = inputVal
} else {
arrOfObj.push({'id':1, 'value':inputVal})
}
console.log(arrOfObj)
}
<button onclick="pushObject()">click</button>
<input type="text" id="mainInput">

js reset the variable on change in select-option menu

i have 2 arrays of data form php and using a select-option menu to get the current key for both arrays.
When the key is chosen from a select menu, i use the key to display this key data for both arrays. If the second array doesnt have the key, it should display nothing.
It works fine when both arrays have identical keys.
But when the 2nd array doesnt have the key, it shows the previous data instead of nothing.
php array is similar to:
$arrays['first']['*random_keys*'] = *random data*;
$arrays['second']['*random_keys*'] = *random data*;
$arrays['keys']['first'] = *list of keys*;
the code:
<select id="selector" name="selected_key" onchange="showContent();">
</select>
<div id="show_selected_option"></div>
<div id="showFirstArrayData"></div>
<div id="showSecondArrayData"></div>
<script>
//both arrays in 1 from php
const arrays = <?php echo json_encode($arrays); ?>;
//keys of first array
const keys_kaunt = <?php echo json_encode(count($arrays['keys']['first'])); ?>;
var text = '<option></option>';
for(var i=0;i<keys_kaunt;i++)
{
text += '<option>' + arrays['keys']['first'][i] + '</option>';
}
//show all options in select
document.getElementById("selector").innerHTML = text;
//show data
function showContent(){
var e = document.getElementById("selector");
var f = e.options[e.selectedIndex].value;
document.getElementById("show_selected_option").value = f;
//first array data
var firstArrayKeys = arrays['first'][f];
var firstKeysOutput= '';
Object.keys(firstArrayKeys).forEach(function (key){
firstKeysOutput += key + arrays['first'][f][key];
});
document.getElementById("showFirstArrayData").innerHTML = firstKeysOutput;
//second array data
var secondArrayKeys = arrays['second'][f];
var secondKeysOutput= '';
Object.keys(secondArrayKeys ).forEach(function (key){
secondKeysOutput += key + arrays['second'][f][key];
});
document.getElementById("showSecondArrayData").innerHTML = secondKeysOutput;
}
</script>
The quastion is how to reset the variable 'f' on changed selector. So it doesnt show the previously selected data if the 2nd array doesnt have the selected key.
thanks, works now. the problem was in generated innerHTML not going away, not in the variable.
If I understand your problem correctly, then you maybe need an if statement.
It sounds like you want to empty the input with id="showSecondArrayData" when arrays['second'] does not contain the key f.
function showContent(){
var e = document.getElementById("selector");
var f = e.options[e.selectedIndex].value;
document.getElementById("show_selected_option").value = f;
// FIRST ARRAY code
//
//second array data
if (f in arrays['second']){
var secondArrayKeys = arrays['second'][f];
var secondKeysOutput= '';
Object.keys(secondArrayKeys ).forEach(function (key){
secondKeysOutput += key + arrays['second'][f][key];
});
document.getElementById("showSecondArrayData").innerHTML = secondKeysOutput;
} else {
document.getElementById("showSecondArrayData").innerHTML = '';
}
}
I'm not an expert in js, so please forgive any mistakes or not keeping with js coding standards.
function showContent(){
document.getElementById("showSecondArrayData").innerHTML = '';
var e = document.getElementById("selector");
var f = e.options[e.selectedIndex].value;
document.getElementById("show_selected_option").value = f;
}
did the trick, ty for the help.

Function output replaces first two rows of my main JSON string

I have a JSON query and I am using console.log to present it:
var json_data = {"headers":["Month","Value","Number"],"rows":[["2018-10-01 00:00:00.0","one",209],["2018-09-01 00:00:00.0","one",274],["2018-09-01 00:00:00.0","five",183],["2018-10-01 00:00:00.0","five",164],["2018-09-01 00:00:00.0","four",214],["2018-10-01 00:00:00.0","four",192],["2018-09-01 00:00:00.0","three",128],["2018-10-01 00:00:00.0","three",125],["2018-09-01 00:00:00.0","two",199],["2018-10-01 00:00:00.0","two",169],["2018-09-01 00:00:00.0","seven",10541],["2018-10-01 00:00:00.0","seven",6139],["2018-10-01 00:00:00.0","six",169],["2018-09-01 00:00:00.0","six",233]]};
document.getElementById("original").innerHTML = json_data.rows;
<div style="background:yellow; "id="original"></div>
<div style="background:red;" id="output"></div>
And for the value "one" I have two numbers (209 and 274).
I am then using a function to groupby which works fine (output). My problem is that when I use the console.log for the initial json_data query, the first two rows are different. It seems that my function replaced the first two rows with the rows of the output (red). The function is given here:
function initialGroupBy(rows) {
const
rowMap = new Map(),
result = [],
dataTemp = [];
// Iterate over the rows.
rows.forEach(row => {
const
// Create a key, it is the first elements joined together.
key = row.slice(0,1).join();
// Check if the Map has the generated key...
if (rowMap.has(key)) {
// The map has the key, we need to add up the values
const
// Get the value for the current key.
storedRow = rowMap.get(key);
// Add the value of the current row to the row in the map.
storedRow[2] += row[2];
} else {
// The key doens't exist yet, add the row to the map.
rowMap.set(key, row);
}
});
// Iterate over all the entries in the map and push each value with the
// summed up value into the array.
rowMap.forEach(value => {
result.push(value);
});
for (i = 0; i < result.length; i++)
{
var object2 = {"date": result[i][0].slice(0,7), "num": result[i][2]};
dataTemp.push(object2);
}
return dataTemp;
}
A full snippet can be found here (Compare the first two rows of the yellow box from the two snippets):
var json_data = {"headers":["Month","Value","Number"],"rows":[["2018-10-01 00:00:00.0","one",209],["2018-09-01 00:00:00.0","one",274],["2018-09-01 00:00:00.0","five",183],["2018-10-01 00:00:00.0","five",164],["2018-09-01 00:00:00.0","four",214],["2018-10-01 00:00:00.0","four",192],["2018-09-01 00:00:00.0","three",128],["2018-10-01 00:00:00.0","three",125],["2018-09-01 00:00:00.0","two",199],["2018-10-01 00:00:00.0","two",169],["2018-09-01 00:00:00.0","seven",10541],["2018-10-01 00:00:00.0","seven",6139],["2018-10-01 00:00:00.0","six",169],["2018-09-01 00:00:00.0","six",233]]};
function initialGroupBy(rows) {
const
rowMap = new Map(),
result = [],
dataTemp = [];
// Iterate over the rows.
rows.forEach(row => {
const
// Create a key, it is the first elements joined together.
key = row.slice(0,1).join();
// Check if the Map has the generated key...
if (rowMap.has(key)) {
// The map has the key, we need to add up the values
const
// Get the value for the current key.
storedRow = rowMap.get(key);
// Add the value of the current row to the row in the map.
storedRow[2] += row[2];
} else {
// The key doens't exist yet, add the row to the map.
rowMap.set(key, row);
}
});
// Iterate over all the entries in the map and push each value with the
// summed up value into the array.
rowMap.forEach(value => {
result.push(value);
});
for (i = 0; i < result.length; i++)
{
var object2 = {"date": result[i][0].slice(0,7), "num": result[i][2]};
dataTemp.push(object2);
}
return dataTemp;
}
const damn = initialGroupBy(json_data.rows);
document.getElementById("original").innerHTML = json_data.rows;
document.getElementById("output").innerHTML =JSON.stringify(damn);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="background:yellow; "id="original"></div>
<br><br>
<div style="background:red;" id="output"></div>
I have tried changing the var to const in many cases. Am I missing a fundamental JavaScript case here?
As your value is an Array object, when you save it in your temporary Map, you're actually using a reference to your original data structure row.
So in the first forEach loop, where you sum the values you're actually changing the original array entry.
The solution is pretty simple, just clone the array:
rowMap.set(key, row.slice());
Another possibility is to use a different array to save the totals.
Here is your code with the fix.
var json_data = {"headers":["Month","Value","Number"],"rows":[["2018-10-01 00:00:00.0","one",209],["2018-09-01 00:00:00.0","one",274],["2018-09-01 00:00:00.0","five",183],["2018-10-01 00:00:00.0","five",164],["2018-09-01 00:00:00.0","four",214],["2018-10-01 00:00:00.0","four",192],["2018-09-01 00:00:00.0","three",128],["2018-10-01 00:00:00.0","three",125],["2018-09-01 00:00:00.0","two",199],["2018-10-01 00:00:00.0","two",169],["2018-09-01 00:00:00.0","seven",10541],["2018-10-01 00:00:00.0","seven",6139],["2018-10-01 00:00:00.0","six",169],["2018-09-01 00:00:00.0","six",233]]};
function initialGroupBy(rows) {
const
rowMap = new Map(),
result = [],
dataTemp = [];
// Iterate over the rows.
rows.forEach(row => {
const
// Create a key, it is the first elements joined together.
key = row.slice(0,1).join();
// Check if the Map has the generated key...
if (rowMap.has(key)) {
// The map has the key, we need to add up the values
const
// Get the value for the current key.
storedRow = rowMap.get(key);
// Add the value of the current row to the row in the map.
storedRow[2] += row[2];
} else {
// The key doens't exist yet, add the row to the map.
rowMap.set(key, row.slice());
}
});
// Iterate over all the entries in the map and push each value with the
// summed up value into the array.
rowMap.forEach(value => {
result.push(value);
});
for (i = 0; i < result.length; i++)
{
var object2 = {"date": result[i][0].slice(0,7), "num": result[i][2]};
dataTemp.push(object2);
}
return dataTemp;
}
const damn = initialGroupBy(json_data.rows);
document.getElementById("original").innerHTML = json_data.rows;
document.getElementById("output").innerHTML =JSON.stringify(damn);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="background:yellow; "id="original"></div>
<div style="background:red;" id="output"></div>
A) The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable -> Link
B) Your problem is that you are actually editing the original object in the initialGroupBy function. Maybe this answer will be helpful.
A different logic applies here and the result is handy:
var json_data = {"headers":["Month","Value","Number"],"rows":[["2018-10-01 00:00:00.0","one",209],["2018-09-01 00:00:00.0","one",274],["2018-09-01 00:00:00.0","five",183],["2018-10-01 00:00:00.0","five",164],["2018-09-01 00:00:00.0","four",214],["2018-10-01 00:00:00.0","four",192],["2018-09-01 00:00:00.0","three",128],["2018-10-01 00:00:00.0","three",125],["2018-09-01 00:00:00.0","two",199],["2018-10-01 00:00:00.0","two",169],["2018-09-01 00:00:00.0","seven",10541],["2018-10-01 00:00:00.0","seven",6139],["2018-10-01 00:00:00.0","six",169],["2018-09-01 00:00:00.0","six",233]]};
function groupBy(accumulator, item) {
const [date,extra,value] = item;
const key = date.slice(0,7);
if(!accumulator[key]){
accumulator[key] = 0
}
accumulator[key] += value;
return accumulator;
}
var damn = json_data.rows.reduce(groupBy,{});
damn = Object.keys(damn).map(function(key){
return {date: key, Value: "Total", num: damn[key]};
})
document.getElementById("original").innerHTML = json_data.rows;
document.getElementById("output").innerHTML =JSON.stringify(damn);
<div style="background:yellow; "id="original"></div>
<div style="background:red;" id="output"></div>

Javascript & jQuery push array to object based on custom attribute

Problem
There are a couple of HTML tags with classes as follows
<span class=​"keyword" column-name=​"Product Group">​Outdoors</span>​
<span class=​"keyword" column-name=​"Material Code">​10001003​</span>​
<span class=​"keyword" column-name=​"Material Code">​10001000​</span>​
All the span needs to be iterated through and a new object would be created with the column-name attribute as its property and the relevant text passed into an array.
Code So Far
I am using the below code but the array passed consists of all the text from the span
var searchCriteria = {};
var keyword = [];
$('.keyword').each(function(index, elem) {
col = $(elem).attr('column-name');
keyword.push($(elem).text());
searchCriteria[col] = (keyword);
});
console.log(searchCriteria);
The above code prepares the object as
{
Material Code: ['Outdoors', '10001003', '10001000']
Product Group: ['Outdoors', '10001003', '10001000']
}
Result Expected
The result of the object which I am expecting is
{
Material Code: ['10001003', '10001000']
Product Group: ['Outdoors']
}
JS Fiddle
Here is a JSFiddle of the same - http://jsfiddle.net/illuminatus/0g0uau4v/2/
Would appreciate any help!
When you use searchCriteria[col] = (keyword);, it does not copy the keyword array. It just stores pointer to that array. So, if you update keyword after assigning it to some variable, it'll also get updated as both of them points to the same array. If you want to copy array you may use .slice() on array. But here it is not needed.
Use the following code instead
var searchCriteria = {};
$('.keyword').each(function(index, elem) {
col = $(elem).attr('column-name');
if ( !Array.isArray(searchCriteria[col]) )
searchCriteria[col] = [];
searchCriteria[col].push($(elem).text());
});
console.log(searchCriteria);
http://jsfiddle.net/0g0uau4v/3/
You can't use the same array as the value for each column. Instead, create a new array each time you encounter a new column, or simply append the value to the existing array if the column-name already exists:
$(function() {
var searchCriteria = {};
$('.keyword').each(function(index, elem) {
var col = $(elem).attr('column-name');
var keyword = searchCriteria[col] ? searchCriteria[col] : [];
keyword.push($(elem).text());
searchCriteria[col] = (keyword);
});
$("#result").text("Result: " + JSON.stringify(searchCriteria));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="keyword" column-name="Product Group">Outdoors</span>
<span class="keyword" column-name="Material Code">10001003</span>
<span class="keyword" column-name="Material Code">10001000</span>
<div id="result"></div>
That was becoz, you were using same updated array for all.
var searchCriteria = {};
var keyword = [];
$('.keyword').each(function(index, elem) {
col = $(elem).attr('column-name');
if( !searchCriteria[col])
searchCriteria[col] = [];
searchCriteria[col].push($(elem).text());
});
console.log(searchCriteria);
Here in this code im searching for, if property doesn't exist . Then make that index as array. And futher you push elements.
Working fiddle
You can instead do this
var searchCriteria = {};
$('.keyword').each(function(){
var key = $(this).attr("column-name");
var value = $('[column-name='+key+']').map(function(){return $(this).text()}).get();
if(!searchCriteria.hasOwnProperty(key)) searchCriteria[key] = value;
});

push JSON object to array is not adding in array

I have a problem I don't know what am doing wrong, below code need to push and JSON Object into array but its not updating, its only showing last pushed element.
var myData = {};
var id = 0;
$("a").on('click', function(){
myData.answers = new Array();
myAns = { id : id, answer : "my answer" };
myData.answers.push(myAns);
id++;
console.log(myData);
});
Here is a Fiddle for same, please help
Move myData.answers = new Array(); out of the click event handler. You're reseting the array every time you click the link:
myData.answers = new Array();
$("a").on('click', function(){
myAns = //etc

Categories

Resources