I have multiple inputs as an array like this:
<input name="data[extras][1][id]" value="1">
<input name="data[extras][1][netto]">
<input name="data[extras][1][tax]">
<input name="data[extras][1][brutto]">
<input name="data[extras][2][id]" value="2">
<input name="data[extras][2][netto]">
<input name="data[extras][2][tax]">
<input name="data[extras][2][brutto]">
i got all extras with:
let extras = $('input[name^=data\\[extras\\]]');
now i would like to iterate through all to create an array out of it but i need for the id for further actions (the 1 or the 2).
i would like to achive something like this:
let id = $('input[name^=data\\[extras\\]\\[UNKNOWN ID\\]\\[id\\]]').val();
i hope anybody can help me.
Greetings
you can receive all ids in jquery like this
$('document').ready(function(){
var values = $('input[name$=\\[id\\]]').map(function(){return $(this).val();}).get();
console.log(values); });
Maybe you could loop trough the inputs and in the loop get the id/index via regexp from the name attribute to query that [id] input?
data\[extras\]\[(\d)\]
Unclear what your expected output would be, but you can easily loop over the collection of elements and parse out the number and the string.
var inputs = document.querySelectorAll('[name^="data\[extras\]"]');
const grouped = Array.from(inputs).reduce(function(o, input) {
const parts = input.name.match(/^data\[extras\]\[(\d+)\]\[(.*)\]$/);
const index = parts[1];
const key = parts[2];
o[index] = o[index] || {};
o[index][key] = input.value;
return o;
}, {});
console.log(Object.values(grouped))
<input name="data[extras][1][id]" value="1-i">
<input name="data[extras][1][netto]" value="1-n">
<input name="data[extras][1][tax]" value="1-t">
<input name="data[extras][1][brutto]" value="1-b">
<input name="data[extras][2][id]" value="2-i">
<input name="data[extras][2][netto]" value="2-n">
<input name="data[extras][2][tax]" value="2-t">
<input name="data[extras][2][brutto]" value="2-b">
Related
I have a function that takes elements from the DOM to update a db on button click. Currently, there is one id for one value...
<input class='total' doc-id='12345678' value='${whateverCurrent.value}'>user updates</field>
<input class='total' doc-id='87654321' value='${whateverCurrent.value}'>user updates</field>
This is the function:
const elements = document.querySelectorAll('.total')
await Promise.all(Array.from(elements).map(async (el) => {
let docId = el.id;
let total = el.value;
await updateDoc(docId, { total });
}))
I now need to break this down such that there are 4 classes of input fields rather than 1 (by quarter). So there will be different elements but with the same id:
<input class='q1' doc-id='12345678' value='${whateverCurrent.value}'>user updates</field>
<input class='q2' doc-id='87654321' value='${whateverCurrent.value}'>user updates</field>
<input class='q2' doc-id='12345678' value='${whateverCurrent.value}'>user updates</field>
I could run the Promise.all function 4 times, once for each class, but that must be wrong, when instead I should somehow....
// (do something here){
await updateDoc(docId, {q1, q2, q3, q4})
}
when I take all the elements and put them into an array and look at them in the console, I get an array of 4 NodeLists.
How do I take these 4 nodeLists and amalgamate them so that every id has its 4 values to pass to the update function?
I'm not really sure if this is what you're looking for. Can you be more specific in what the updateDoc function expects as arguments?
Anyway, I coded something that collects all the quarterly values per doc-id and produces an object of following form:
{
1234 :
{
q1 : 7
q2 : 9
},
...
}
const elements = document.querySelectorAll('input')
const docsPerQ = {};
elements.forEach(e => {
const docId = e.getAttribute('doc-id');
const val = e.value;
const quarter = e.className;
if(!(docId in docsPerQ)) docsPerQ[docId] = {};
docsPerQ[docId][quarter] = val;
});
console.log(docsPerQ);
<input type="text" class="q1" value="7" doc-id="1234">
<input type="text" class="q1" value="2" doc-id="5678">
<input type="text" class="q2" value="3" doc-id="5678">
<input type="text" class="q2" value="9" doc-id="1234">
EDIT
I changed the code a bit so the produced output is in a more manageable form. It's now an array of objects with some extra keys attached:
[
{
docId: 1234,
quarters: {
q1: 7,
q2: 3
}
},
...
]
const elements = document.querySelectorAll('input');
const QsPerDoc = [];
elements.forEach(e => {
const docId = e.getAttribute('doc-id');
const val = e.value;
const quarter = e.className;
const entry = QsPerDoc.find(e => e.docId === docId);
// find returns undefined if nothing's found. undefined is a falsy value
if(!entry) {
let quarters = {};
quarters[quarter] = val;
QsPerDoc.push({
docId : docId,
quarters
});
}
else {
entry.quarters[quarter] = val;
}
});
console.log(QsPerDoc);
<input type="text" class="q1" value="7" doc-id="1234">
<input type="text" class="q1" value="2" doc-id="5678">
<input type="text" class="q2" value="3" doc-id="5678">
<input type="text" class="q2" value="9" doc-id="1234">
Maybe this works better? Hope it does. I wonder, is the updateDoc function something you can change so it can accept arrays?
You could access them like this:
console.log(QsPerDoc[0].docId);
console.log(QsPerDoc[0].quarters.q1);
(Note: I also changed the name of the object/array to QsPerDoc instead of DocsPerQ, which was not aplty named)
Anyway I have to get back to work instead of procrastinating on stackoverflow ;)
I want to create a form where I will perform an operation with the values entered by the user, but when the function runs, I get NaN return. Thank you in advance for the help.
function test() {
var age = document.getElementsByName("person_age").value;
var weight = document.getElementsByName("person_weight").value;
var size = document.getElementsByName("person_size").value;
document.getElementById("result").innerHTML = weight + size + age;
}
<form>
<input type="text" name="person_age">
<input type="text" name="person_size">
<input type="text" name="person_weight">
<input type="button" value="calculate" onclick="test();">
</form>
<h3 id="result"></h3>`
Output:
NaN
When I get the values from the user and run the function, I get NaN feedback. how can i solve this problem.
There are multiple errors that you have to correct
1) When you use getElementsByName, It will return NodeList array like collection. So you have to get the element by using index as:
var age = document.getElementsByName( "person_age" )[0].value;
2) If you need sum of all three value then you have to convert it into Number type because document.getElementsByName( "person_age" )[0] give you value in String type. So you can do as:
+document.getElementsByName( "person_age" )[0].value
function test() {
var age = +document.getElementsByName("person_age")[0].value;
var size = +document.getElementsByName("person_size")[0].value;
var weight = +document.getElementsByName("person_weight")[0].value;
document.getElementById("result").innerHTML = weight + size + age;
}
<form>
<input type="text" name="person_age">
<input type="text" name="person_size">
<input type="text" name="person_weight">
<input type="button" value="calculate" onclick="test();">
</form>
<h3 id="result"></h3>
Just a Suggestion: You can use Document.getElementById if you want to directly access the value. Just add an ID property in your element. It will return a string value, convert that to int and you're good to go.
function test() {
var age = document.getElementById("person_age").value;
var weight = document.getElementById("person_weight").value;
var size = document.getElementById("person_size").value;
document.getElementById("result").innerHTML = parseInt(weight) + parseInt(size) + parseInt(age);
}
<form>
<input type="text" name="person_age" id="person_age">
<input type="text" name="person_size" id="person_size">
<input type="text" name="person_weight" id="person_weight">
<input type="button" value="calculate" onclick="test();">
</form>
<h3 id="result"></h3>
getElementsByName will always return an array-like nodelist so, if you were to use it you would need to access the first index [0]. Instead add a class to each input and use querySelector to target it.
The value of an input will always be a string (even if the input is type "number"), so you need to coerce it to a number, either by using Number or by prefixing the value with +.
So, in this example I've updated the HTML a little by adding classes to the inputs, and changing their type to "number", and removing the inline JS, and updated the JS so that the elements are cached outside of the function, an event listener is added to the button, and the values are correctly calculated.
// Cache all the elements using querySelector to target
// the classes, and add an event listener to the button
// that calls the function when it's clicked
const ageEl = document.querySelector('.age');
const weightEl = document.querySelector('.weight');
const sizeEl = document.querySelector('.size');
const result = document.querySelector('#result');
const button = document.querySelector('button');
button.addEventListener('click', test, false);
function test() {
// Coerce all the element values to numbers, and
// then display the result
const age = Number(ageEl.value);
const weight = Number(weightEl.value);
const size = Number(sizeEl.value);
// Use textContent rather than innerHTML
result.textContent = weight + size + age;
}
<form>
<input type="number" name="age" class="age" />
<input type="number" name="size" class="size" />
<input type="number" name="weight" class="weight" />
<button type="button">Calculate</button>
</form>
<h3 id="result"></h3>`
I'm trying to do this:
<input type="checkbox" name="appliances[microwave]">
<input type="checkbox" name="appliances[coffee-machine]">
<input type="checkbox" name="appliances[grill]">
and get access to this array in javascript like this
1.
var myarr = document.getElementsByName('appliances');
alert('here ' + myarr);
result: alert shows "here [object NodeList]"
2.
var myarr = document.getElementsByName('appliances');
alert('here ' + myarr['grill']);
result: alert shows "here undefined"
How may I get access to this array?
Your elements all have different names as far as HTML is concerned, "appliances[microwave]", "appliances[coffee-machine]", etc. Those names are only special to certain software (for instance, PHP will handle them on a form submission).
You can find all elements whose name starts with appliances by using querySelectorAll with the selector input[name^=appliances]. Then you access the entries in that NodeList by index (0, 1, and 2):
const checkboxes = document.querySelectorAll("input[name^=appliances]");
for (let n = 0; n < checkboxes.length; ++n) {
console.log(`${checkboxes[n].name} checked? ${checkboxes[n].checked}`);
}
<input type="checkbox" checked name="appliances[microwave]">
<input type="checkbox" name="appliances[coffee-machine]">
<input type="checkbox" name="appliances[grill]">
<!-- A fourth one just to show that it won't get selected: -->
<input type="checkbox" name="something-else">
If you want to access them by the names in [], you could create an object and put them on the object as properties:
function getNamedElementObject(baseName) {
const result = {};
// NOTE: The next line assumes there are no `]` characters in `name`
const list = document.querySelectorAll(`[name^=${baseName}]`);
for (const element of list) {
const match = element.name.match(/\[([^]+)\]/);
if (match) {
const propName = match[1]
result[propName] = element;
}
}
return result;
}
const checkboxes = getNamedElementObject("appliances");
console.log(`checkboxes["microwave"].checked? ${checkboxes["microwave"].checked}`);
console.log(`checkboxes["coffee-machine"].checked? ${checkboxes["coffee-machine"].checked}`);
console.log(`checkboxes["grill"].checked? ${checkboxes["grill"].checked}`);
// You could also loop through by getting an array from `Object.values`:
for (const checkbox of Object.values(checkboxes)) {
console.log(`${checkbox.name} checked? ${checkbox.checked}`);
}
<input type="checkbox" checked name="appliances[microwave]">
<input type="checkbox" name="appliances[coffee-machine]">
<input type="checkbox" name="appliances[grill]">
<!-- A fourth one just to show that it won't get selected: -->
<input type="checkbox" name="something-else">
Or you could use a Map:
function getNamedElementMap(baseName) {
const result = new Map();
// NOTE: The next line assumes there are no `]` characters in `name`
const list = document.querySelectorAll(`[name^=${baseName}]`);
for (const element of list) {
const match = element.name.match(/\[([^]+)\]/);
if (match) {
const propName = match[1]
result.set(propName, element);
}
}
return result;
}
const checkboxes = getNamedElementMap("appliances");
console.log(`checkboxes.get("microwave").checked? ${checkboxes.get("microwave").checked}`);
console.log(`checkboxes.get("coffee-machine").checked? ${checkboxes.get("coffee-machine").checked}`);
console.log(`checkboxes.get("grill").checked? ${checkboxes.get("grill").checked}`);
// You could also loop through via the iterator from the `values` method:
for (const checkbox of checkboxes.values()) {
console.log(`${checkbox.name} checked? ${checkbox.checked}`);
}
<input type="checkbox" checked name="appliances[microwave]">
<input type="checkbox" name="appliances[coffee-machine]">
<input type="checkbox" name="appliances[grill]">
<!-- A fourth one just to show that it won't get selected: -->
<input type="checkbox" name="something-else">
i have two variables name and location which are provided by two <input type="text">. I need to get an outcome of Smith_California but I am getting an output of userName_userLoca in the console.
Any suggestions would help.
currently, I have:
HTML:
<form class="inputContainer" id="inputContainer" methed="post">
<label for="userNam">Your Name</label>
<input type="text" class="userNam" id="userNam" name="userNam" />
<label for="userLoca">Your Location</label>
<input type="text" class="userLoca" id="userLoca" name="userLoca" />
<button class="vButton" id="vButton" type="submit" onclick="testfun()">
Begin Test
</button>
</form>
Javascript:
var userName = document.getElementById('userNam');
var userLoca = document.getElementById('userLoca');
var userSID = ['userName', 'userLoca'];
console.log(userSID.join('_'));
Remove the quotes and use .value:
var userSID = [userName.value, userLoca.value];
You are accessing dom-element, using var userName = document.getElementById('userNam');.
Try with var userName = document.getElementById('userNam').value.
Also remove the quotes from var userSID = ['userName', 'userLoca']; and use it like below
var userSID = [userName, userLoca];
I had one row with three fields: received, issue, balance
<input type="text" name="rcv" class="rcv"/>
<input type="text" name="issue" class="issue"/>
<input type="text" name="blnc" class="balance"/>
I calculated the balance for each row easily, but how do I calculate more than one row?
Each row has receive, issue and balance fields.
How do I calculate each row's balance field?
I tried like this for multiple row but it's not working:
$('.t_rtn, .t_rcv').each(function(){
$(this).on('blur',function(){
var totalRcv = $('.t_rcv').val();
var totalRtn = $('.t_rtn').val();
// console.log( $('t_rtn').next('.consume').val() );
$('t_rtn').next('.consume').val(totalRcv-totalRtn);
});
you need to parse The value of textbox as it returns string not int
$('.t_rtn, .t_rcv').each(function(){
$(this).on('blur',function(){
var totalRcv = parseInt($('.t_rcv').val()) || 0;
var totalRtn = parseInt($('.t_rtn').val()) || 0;
// console.log( $('t_rtn').next('.consume').val() );
$('t_rtn').next('.consume').val(totalRcv-totalRtn);
});
If your code is being run on document.ready it will only be applied to elements which exist at that point.
You'd be better with :
$(document).on('blur','.t_rtn, .t_rcv',function(){
var val = $(this).val();
...
});
try this..
$(document).on('blur','.receive, .return', function()
{
var $row = $(this).closest(".row");
var totalRcv = parseInt($row.find('.receive').val()) || 0;
var totalRtn = parseInt($row.find('.return').val()) || 0;
$row.find('.balance').val(totalRcv - totalRtn);
});
In addition to parsing the string values into integers you also need to use the correct selectors for those input elements. t_rtn is not the right class name, for example. And if doing this in rows you will want to grab the correct element from the current row (you already did this correctly for the consume field)
Fixed html (Example.. I chose to use div with class name = row):
<div class='row'>
<input type="text" name="rcv" class="receive"/>
<input type="text" name="issue" class="return"/>
<input type="text" name="blnc" class="balance"/>
</div>
<div class='row'>
<input type="text" name="rcv" class="receive"/>
<input type="text" name="issue" class="return"/>
<input type="text" name="blnc" class="balance"/>
</div>
<div class='row'>
<input type="text" name="rcv" class="receive"/>
<input type="text" name="issue" class="return"/>
<input type="text" name="blnc" class="balance"/>
</div>
Fixed code:
$(document).on('blur','.receive, .return', function()
{
var $row = $(this).closest(".row");
var totalRcv = parseInt($row.find('.receive').val()) || 0;
var totalRtn = parseInt($row.find('.return').val()) || 0;
$row.find('.balance').val(totalRcv - totalRtn);
});
I took the liberty of fixing some inconsistencies with the class names used. I tried to match them up to the variables for totalRcv and totalRtn so that now the balance shows as receipt minus return. If the user enters non-numeric data, it defaults the value to 0 before calculating.
Example fiddle here: http://jsfiddle.net/cp81g4nf/1/
I think problem is because you are subtracting 2 Strings. .val returns an String.
Convert them in number before subtracting like bellow
$('t_rtn').next('.consume').val((+totalRcv)-(+totalRtn));