Can't get all array key and values into array - javascript

When i tried to see all input values, its always showing last ones.
function addInput() {
$('.addElement').append('<label>Sağlık Etkisi</label><input id="health" name="health[]" type="text" class="form-control message">');
$('.addElement').append('<label>Yaşam Tarzı Önerisi</label><input id="lifeStyle" name="lifeStyle[]" type="text" class="form-control message">');
$('.addElement').append('<label>Öneriler</label><input id="advice" name="advice[]" type="text" class="form-control message">');
}
I'm appending 3 input to my form.
$('#test').submit(function(e) {
e.preventDefault();
var text = [];
$("input[name='health[]']").each(function(index, item) {
text['health'] = item.value;
});
$("input[name='lifeStyle[]']").each(function(index, item) {
text["lifeStyle"] = item.value;
});
$("input[name='advice[]']").each(function(index, item) {
text["advice"] = item.value;
});
I did text[index]['health'], and this gave me error too.
this code on output, always giving me last 3 input value.
Sorry for my english.

The issue is because you're overwriting the values of the health, lifeStyle and advice properties in every iteration, hence on the final values in each loop are accessible.
One solution to fix this would be to build arrays of the input values and assign those to the properties instead:
$('#test').submit(function(e) {
e.preventDefault();
var healthVals = $("input[name='health[]']").map(function() { return this.value; }).get();
var lifestyleVals = $("input[name='lifeStyle[]']").map(function() { return this.value; }).get();
var adviceVals = $("input[name='advice[]']").map(function() { return this.value; }).get();
var text = [];
text['health'] = healthVals;
text['lifeStyle'] = lifestyleVals;
text['advice'] = adviceVals;
});
Also note that the fact you're looping over the appended elements implies that there can be multiple copies of them. In which case you should remove the id attribute from the HTML you append, as it will result in duplicates which is invalid.

Related

Storing latest input values in an array

I have the following HTML:
<input class="type" id="carbNumber">
<input class="type" id="otherId">
I want to store the input values in an object.
let data = {
inputData: []
}
document.querySelector('input').addEventListener('blur', updateItem)
function updateItem(){
data.inputData.push(this.value)
}
As I have multiple input elements I want to store their values in an array. If I input another value in the same input element - in which I had already input some other value - how can I figure out where I have stored the previous value the first time and therefore replace it with the new value?
You can use the index number from the input elements as they are returned by querySelectorAll:
const data = {
inputData: []
}
// Use the callback argument of `Array.from` and the `i` index:
Array.from(document.querySelectorAll('input'), (inp, i) => {
inp.addEventListener('input', updateItem.bind(inp, i)); // pass `i`
});
function updateItem(i){ // capture `i`
data.inputData[i] = this.value;
console.log('inputData:' + data.inputData);
}
<input id="a">
<input id="b">
<input id="c">
NB: I used the input event to display the results immediately as you type.
Simply do not use an array, use an object.
The object will map the ids of your input elements to their values
"use strict";
(function() {
var values = {};
function updateAllInputs() {
var inputs = document.querySelectorAll('input');
Array.prototype.forEach.call(inputs, function (input) {
// ensures exactly one value per input (if all inputs have ids, adjust as needed)
values[input.id] = input.value;
});
}
// if you still need an array for some reason, you can create one from the object.
function getSnapshotOfInputValuesAsArray() {
return Object.keys(values).map(function(key) {
return values[key];
});
}
}());

Push an object to array, obejct overwritting the previos one

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.

Comparing an array to text in JavaScript

How could one go about checking all the document's elements' data attributes, and if the contents of an attribute match a value from in an array, do something?
I have an array that I'm creating by grabbing the name and value attributes from text inputs. I want to, for example, compare the value of name "X" to the value of a span with a data-attribute of "X".
The code I currently have is this:
bulletinPreview.prototype.updatePreview = function () {
var dataValues = new Array();
$(".edit-bulletin input[type=text]").each(function () {
var $this = $(this),
dataName = $this.attr("name"),
dataValue = $this.attr("value");
dataValues.push({
"name": dataName,
"value": dataValue
});
});
$(".bulletin-preview .editable").each(function () {
var $this = $(this);
if ($.inArray($this.data("title"), dataValues.name !== -1)) {
$this.text(dataValues[1].value);
}
});
};
It replaces the text for ALL elements with a data-title of title the second value (because I'm explicitly saying dataValues[1] just to see something work). How do I take this and make it modular, so that it just runs through all the elements, runs through the array, and if two values match, do something?
I think you're looking for this:
var $preview = $(".bulletin-preview");
$.each(dataValues, function(index, entry) {
var $edit = $preview.find('.editable[data-title="' + entry.name + '"]');
$edit.text(entry.value); // No-op if no match
});
That assumes none of the names contains double quotes.
If the repeated searches through $preview bother you, you can do one search and make yourself a map:
var map = {};
$(".bulletin-preview .editable").each(function() {
map[this.getAttribute("data-title")] = this;
});
$.each(dataValues, function(index, entry) {
var edit = map[entry.name];
if (edit) {
$(edit).text(entry.value);
}
});

Separate array of elements by attribute

Let's say I've got a form with several inputs, and I use a pretty standard jQuery statement to get them all:
var inputs = $("#some-form").find("input")
Now, I'd like to act on those inputs, but let's say I want to treat the radio button and/or checkbox groups as a single thing. How can I split inputs out into elements grouped by an attribute, say name. Note, that I don't know what the name is going to be when the processing starts.
In human terms, I need the logic do do something along the lines of:
Let me iterate over the list of inputs. For each input, let me check
to see if it's already been added to a placeholder array. If so,
leave it alone. If not, add it and everything with it's name to said
placeholder array (as a sub array).
Essentially, I'd like something like this:
[[<input type="text" name="name1">], [<input type="radio" name="name2">,<input type="radio" name="name2">]]
Try using attribute selector inside a filter.
var $formInput = $('#some-form').find('input');
var inputText = $formInput.filter('[type=text]')
var otherInput = $formInput.filter("[type=radio]")
.add($formInput.filter('[type=checkbox]'));
or even better
var otherInput = $formInput.filter(function () {
return this.type == 'radio' || this.type == 'checkbox';
});
DEMO: http://jsfiddle.net/utwaf/
How can I split inputs out into elements grouped by an attribute, say name
var elements = []; //elements by name
var $formInput = $('#some-form').find('input');
elements.push($formInput.filter(function() {
return this.name == 'name1';
});
elements.push($formInput.filter(function() {
return this.name == 'name2';
});
Note: All elements pushed into the array are jQuery objects.
function getInputsPartitioned(formEl) {
var inputEls = formEl.querySelectorAll("input");
var inputsByName = Object.create(null);
for (var i = 0; i < inputEls.length; ++i) {
var inputEl = inputEls[i];
var name = inputEl.name;
if (!(name in inputsByName)) {
inputsByName[name] = [];
}
inputsByName[name].push(inputEl);
}
// `inputsByName` now looks like this:
// {
// name1: [<input type="text" name="name1">],
// name2: [<input type="radio" name="name2">, <input type="radio" name="name2">]
// }
// To get it into arrays:
return Object.keys(inputsByName).map(function (name) {
return inputsByName[name];
});
}
Bonus: no jQuery needed.

JavaScript: Why isn't my closure working?

The following code is only assigning the value of the last .enter_form input to the last MYAPP.list[0].responses[MYAPP.score.round].form[key] (where key is the only thing that varies). I think it's because only the last value of the key is being passed to addEntry(), but I can't figure out how to get around that.
$('.enter_form input').each(function() {
var key = $(this).attr('id');
var val = $(this).val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form = [];
function addEntry() {
return function(k) {
MYAPP.list[0].responses[MYAPP.score.round].form[k] = {'entry': userDict[k]};
}(key);
}
addEntry();
}
Your addEntry function is redundant since each iteration is already run inside it´s own scope so key and val are preserved properly (hope that explanation makes sense). Also the array you where inserting into was overwritten each iteration as well, so at the end of the .each() you end up with an array with only 1 value. It should also be an object rather then an array, even if the id's are numerical.
// you where overwriting this each iteration
MYAPP.list[0].responses[MYAPP.score.round].form = {};
$('.enter_form input').each(function() {
var el= $(this); // cache instead of creating a new jQuery object each time
var key = el.attr('id');
var val = el.val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form[key] = {'entry': userDict[key]};
}); // ); was also missing
Should work.
It's a bit hard to work out what it's meant to do, but I think this is probably it:
MYAPP.list[0].responses[MYAPP.score.round].form = [];
$('.enter_form input').each(function() {
var $this = $(this),
key = this.id,
val = $this.val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form[key] = {
'entry': val
};
});
That's based on your saying that "...key is the only thing that varies" (presumably $(this).val() also varies, but I took your point). It will add entries to MYAPP.list[0].responses[MYAPP.score.round].form for each of the form's input ids, as well as adding them to the userDict map.
As a side note, if the id values on the input elements aren't purely numeric, then I suspect you want to start with a blank object:
MYAPP.list[0].responses[MYAPP.score.round].form = {};
// ^^-- change is here
...rather than an empty array:
MYAPP.list[0].responses[MYAPP.score.round].form = [];
...although since arrays are objects, it works even if you're adding non-numeric properties.
Off-topic: No need for $(this).attr('id'). Just use this.id.

Categories

Resources