I'm using bootstrap validator to cloning the input and radio elements.
It is working fine, but i have issue while receiving these values as JavaScript array. Because i always have hidden input and radio elements in the DOM so it send empty object.
How i map my array object to receive values
var kids = $(".form--group").map(function() {
return {
kidName: $(this).find('.thevoornaam').val(),
newDob: $(this).find('.date_of_birth').val(),
}
}).get();
console.log(kids)
I'm receiving values like this..
[{kidName: "Test", newDob:"20"},{kidName: "", newDob:""} ]
Always receive second object with empty string.
How can remove the object from array if values are empty or undefined is..
I hope you guys understand my question.
Thanks in advance.
You can use filter to filter out the empty object like this
var kids = $(".form--group").map(function() {
return {
kidName: $(this).find('.thevoornaam').val(),
newDob: $(this).find('.date_of_birth').val(),
}
}).get();
kids = kids.filter(function (kid) {
return kid.kidName && kid.newDob;
});
console.log(kids)
If you want to exclude the item when every property is empty, undefined or 0;
let obj = [{kidName: "Test", newDob:"20"},{kidName: "", newDob:""} ];
let filtered = obj.filter(e=>{
for(let p in e){
if(e[p]){
return true;
}
}
});
console.log(filtered);
Check the strings before you create the objects:
$(document).ready(function(){
var kids = $(".form--group").map(function() {
var kidName = $(this).find('.thevoornaam').val();
var dob = $(this).find('.date_of_birth').val();
var result_arr = [];
if(kidName || dob)
{
var obj = {kidName: kidName, newDob: dob}
result_arr.push(obj);
}
return result_arr;
}).get();
console.log(kids)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form--group">
<input class="thevoornaam" value="Test Name" />
<input class="date_of_birth" value="Test Date" />
</div>
<div class="form--group">
<input class="thevoornaam" value="" />
<input class="date_of_birth" value="" />
</div>
<div class="form--group">
<input class="thevoornaam" value="Test Name" />
<input class="date_of_birth" value="Test Date" />
</div>
Related
Looks like my main issue was using .val() when I should have been using map, thank you #Barmar!
Though I'm still looking for a way to achieve the second array structure at the bottom of my post. It seems like the HTML structure would have to be:
<div>
<input type="text" name="student[1][name]">
<input type="number" name="student[1][score]">
<input type="text" name="student[2][name]">
<input type="number" name="student[2][score]">
<input type="text" name="student[3][name]">
<input type="number" name="student[3][score]">
</div>
The challenge with this is the ID number is dynamic, so I'm not sure how to fit this in a Jquery selector. Would I just be selecting by "student" i.e.
let input_names = $('input[name^="student["]').map(function() {
return this.value;
}).get();
I have a lot of inputs that are of the same kind so I want them in arrays, i.e.
<div>
<input type="text" name="name_[1]">
<input type="number" name="score_[1]">
<input type="text" name="name_[2]">
<input type="number" name="score_[2]">
<input type="text" name="name_[3]">
<input type="number" name="score_[3]">
</div>
The number in-between the brackets is the ID grouping related elements together. I want to be able to send all the values in arrays in an AJAX request but can't seem to figure it out. Only the first elements get sent, not an array
let input_names = $('input[name^="name_"]').val();
let input_scores = $('input[name^="score_"]').val();
$.ajax({
url: "../util/funcs.php",
async: true,
data: {
a: "backendFunction",
input_names: input_names,
input_scores: input_scores
}
})
.done(function(data) {
console.log("Success");
})
.fail(function() {
console.log("Error");
.always(function() {
// alert( "complete" );
});
I want a way to neatly send them to the backend, either as separate arrays by name parameter or ideally grouped by ID. So the $_REQUEST would look something like:
[ids] =>
[1, 2]
[names] =>
["alex", "john"]
[scores] =>
[30, 70]
Or even better:
[1] =>
[name] => "alex"
[score] => "30"
[2] =>
[name] => "john"
[score] => "70"
Unfortunately either way I try, the AJAX only seems to send the first of each input, rather than arrays. Please help!
.val() only returns the value of the first element that matches the selector, not all of them. You need to loop over all the matches to get all the values.
let input_names = $('input[name^="name["]').map(function() {
return this.value;
}).get();
let input_scores = $('input[name^="score["]').map(function() {
return this.value;
}).get();
Here is a solution to get your desired object format:
$(function() {
let result = $('input').map(function() {
return { name: this.name, value: this.value };
}).get().reduce((acc, obj) => {
let num = obj.name.replace(/[^\d]+/g, '');
let key = obj.name.replace(/_.*$/, '');
if(!acc[num]) {
acc[num] = {};
}
acc[num][key] = obj.value;
return acc;
}, {});
console.log('result:', result);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input type="text" name="name_[1]" value="Alex">
<input type="number" name="score_[1]" value="101">
<input type="text" name="name_[2]" value="Berta">
<input type="number" name="score_[2]" value="102">
<input type="text" name="name_[3]" value="Dora">
<input type="number" name="score_[3]" value="103">
</div>
Output:
result: {
"1": {
"name": "Alex",
"score": "101"
},
"2": {
"name": "Berta",
"score": "102"
},
"3": {
"name": "Dora",
"score": "103"
}
}
Notes:
first, get all input elements and build an array of { name, value } objects
then, use a .reduce() to accumulate the desired object format
tweak the .replace() of num and key if you have different name input patterns
<input type="text" class="name_">
<input type="number" class="score_">
<input type="text" class="name_">
<input type="number" class="score_">
<input type="text" class="name_">
<input type="number" class="score_">
<input class="submit" type="button" value="submit" />
<script>
$('.submit').click(function(){
nam = $('.name_');
scr = $('.score_');
naml = nam.length;
myar = new Array;
i=0;
for(i=0;i<naml;i+=1)
{
myar[i] = {'name':nam.eq(i).val(),'score':scr.eq(i).val()};
}
alert(JSON.stringify(myar));
});
</script>
What is the simplest way to check with jQuery if we have multiple input fields on the page with the same value?
Thank you all!
You can iterate all input elements, store their value in a hash table, and check if the value was already there:
var hash = Object.create(null),
result = [].some.call(document.getElementsByTagName('input'), function(inp) {
if(hash[inp.value]) return true;
hash[inp.value] = true;
});
Get all the input elements, sort and check if there are duplicates.
var elements = document.getElementsByTagName("input")
var values = [];
for (var i = 0; i < elements.length; i++) {
values.push(elements[i].value);
}
var sortedValues = values.sort();
for (var o = 0; o < values.length-1; o++) {
if (values[o] == values[o+1])
alert ('Duplicate!');
}
You can loop thru all inputs and generate a data structure like below.
var inputs = {};
$("input").each(function(i, elem) {
if (inputs.hasOwnProperty(elem.value)) {
inputs[elem.value] += 1;
} else {
inputs[elem.value] = 1;
}
});
alert (JSON.stringify(inputs, null, 4))
A Demo
The solution is to write a loop and iterate through each input field for a possible match. If you're using jQuery, then it's actually very simple.
Let's say we have a simple HTML page with 3 input fields.
HTML:
<input type="text" name="input1">
<input type="text" name="input2>
<input type="text" name="input3">
Then we use the jQuery each() method to iterate over the fields. Mainly saying, we iterate over all the input fields and get their values. Then we again iterate through all the input fields (so were actually creating a nested loop) and check if any of them match the currently iterating input value.
jQuery:
var currentInput;
$("input").each(function(index) {
currentInput = $(this);
$("input").each(function(index) {
if currentInput.val() === $(this).val() {
alert("Error: input fields match found");
}
});
});
I would like to provide a more efficient answer when it comes to checking for duplicate values in multiple input fields. When it comes to comparing values we need to,
Iterate and keep the current element somewhere temporarily
Re-iterate and check against the previously kept value whether its a duplicate
When performing the step 2, we need to make sure that we skip comparing the previously kept (step 1) value against itself.
If I am not wrong, I have seen step 1 and 2 in all above answers but not the step 3.
The following code will do all those 3 steps.
var eqArr = [];
var currentInput;
$("input").each(function(k1, v1) {
if($(v1).val() != ''){
currentInput = $(v1);
$("input").each(function(k2, v2) {
if(k1 !== k2 &&
currentInput.val() === $(v2).val() &&
$.inArray($(this).attr('id'), eqArr) === -1){
eqArr.push($(this).attr('id'));
}
});
}
});
In the above code I am collecting id's of those input fields of those duplicates (in array). After performing the above logic, doing following simple check will tell you whether you have duplicates or not.
if(eqArr.length > 0){
//It means we have duplicates
}
var eqArr = [];
var currentInput;
$("input").each(function(k1, v1) {
if ($(v1).val() != '') {
currentInput = $(v1);
$("input").each(function(k2, v2) {
if (k1 !== k2 &&
currentInput.val() === $(v2).val() &&
$.inArray($(this).attr('id'), eqArr) === -1) {
eqArr.push($(this).attr('id'));
}
});
}
});
console.log(eqArr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Input Field Duplicates</title>
</head>
<body>
<input type="text" name="input1" id="i1" value="bbb">
<input type="text" name="input2" id="i2" value="aaa">
<input type="text" name="input3" id="i3" value="aaa">
<input type="text" name="input3" id="i4" value="fff">
<input type="text" name="input3" id="i5" value="bbb">
<input type="text" name="input3" id="i6" value="ccc">
<input type="text" name="input3" id="i7" value="bbb">
<input type="text" name="input3" id="i8" value="bbb">
</body>
</html>
I want to remove an element from the array ids if the element doesn't exist.
<div id="nl-form-0" >
<input type="text" id='dynamic_translation_0_0' value="15" />
<input type="text" id='dynamic_translation_0_1' value="15" />
<input type="text" id='dynamic_translation_0_2' value="15" />
<input type="text" id='dynamic_translation_1_2' value="15" />
</div>
ids = [
"transliterateTextarea",
"dynamic_translation_0_0",
"dynamic_translation_0_1",
"dynamic_translation_0_2",
"dynamic_translation_1_0",
"dynamic_translation_1_1",
"dynamic_translation_1_2"];
check_remove_ids_array(ids);
console.log(ids);
console.log($("#dynamic_translation_1_1").length);
function check_remove_ids_array(array_in) {
array_length = array_in.length;
for (n = 0; n <= array_length; n++) {
if ($("#" + array_in[n]).length == '0') {
removeValue(ids,array_in[n]);
}
}
}
function removeValue(arr, value) {
var array = arr;
for (var i = array.length-1; i--;) {
if (array[i] === value) {
array.splice(i, 1);
}
}
return array;
}
In the above code dynamic_translation_1_1 does not exist. I want to remove that or any other element from the array ids if the element doesn't exist
Why does/did it not work?
Basically you had a return and assigning problem. Since there are no reference parameters in JavaScript you have to assign the returned array back to the initial ids. Same goes for your removeValue() function.
Suggestion
Use the array.filter() prototype instead. It solves your problem more elegantly.
Example
<html>
<head>
<script src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js'></script>
<script>
$(document).ready(function(){
ids = ["transliterateTextarea", "dynamic_translation_0_0", "dynamic_translation_0_1", "dynamic_translation_0_2", "dynamic_translation_1_0", "dynamic_translation_1_1", "dynamic_translation_1_2"];
ids = check_remove_ids_array(ids); //We have to assign it back, else we always get the initial ids array!
console.log(ids);
console.log($("#dynamic_translation_1_1").length);
});
function check_remove_ids_array(array_in){
array_length = array_in.length; //Is not required in this example anymore.
//We use the filter function instead.
return array_in.filter(function(item){return $("#" + item).length > 0})
};
</script>
</head>
<body>
<input type = 'text' id = 'dynamic_translation_0_0' value = '15' />
<input type = 'text' id = 'dynamic_translation_0_1' value = '15' />
<input type = 'text' id = 'dynamic_translation_0_2' value = '15' />
<input type = 'text' id = 'dynamic_translation_1_2' value = '15' />
</body>
</html>
I have created form like this:
<form role="form">
<div class="emailRow">
<label ng-model="emailLbl" for="userEmailID">Email ID</label>
<input type="text" ng-model="user.emailId" name="userEmailID" id="userEmailID" placeholder="Enter your email ID" required />
<div ng-if="getErrorMessage('emailId','1')">
{{getErrorMessage('emailId')}}</div>
</div>
<br/>
<div class="passwordRow">
<label ng-model="passwordLbl" for="userPassword">Password</label>
<input type="password" ng-model="user.password" name="userPassword" id="userPassword" placeholder="Enter your password" required />
<div ng-if="getErrorMessage('password','2')">
{{getErrorMessage('password')}}</div>
</div>
<br/>
<div class="buttondRow">
<button class="button loginBtn" ng-click="loginSubmit(user)">Show Login Form</button>
</div>
</form>
I am validating emailId and password using server side validations and passing error list as response. Now, I want to display error messages at top in order of fields.
So, in getErrorMessage() method, I have passed fieldName along with field's sequence no.
and I have created hashmap as follows:
$scope.getErrorMessage = function(errorCode,sequenceNo) {
for ( var i = 0; i < data.validationErrors.length; i++) {
if(data.validationErrors[i].errorCode == errorCode){
hashmap[sequenceNo] = data.validationErrors[i].errorDescription;
return data.validationErrors[i].errorDescription;
}
}
}
Now I want to sort this hashmap based on key which is my field sequence no
How should I do this in javascript or angualrjs?
Thanks in advance.
bit roundabout...
function compare(a,b){
if(+a && +b){
return (+a) - (+b);
}
return a.localeCompare(b);
}
var hm={};
hm[1] = 55;
hm[3] = 13;
hm[12] = 22;
var keys = Object.keys(hm);
keys.sort(compare);
for(var i in keys){
console.log(keys[i], hm[keys[i]]); // or something else that you might want to do with the details
}
I couldn't understand why you are calling/naming it as hashmap, while it is seems to be a plain array of string as:
a[1] = "please enter...."
a[2] = "please enter...."
:
:
In javascript/angular you can define your array as:
var arr = [] ; // note here... not curly braces
then you can call javascript function sort() as
arr.sort();
Otherwise your can use simple javascript for loop or angular.forEach() loop to do your job.
You can try this using lodash:
var hashmap={};
var array;
hashmap[2] = "Please enter password";
hashmap[1] = "Please enter emailId";
hashmap[3] = "Please enter name";
_.sortBy(hashmap, function(n) {
array = hashmap;
});
console.log(array);
See https://jsfiddle.net/W4QfJ/288/
How can I get the value of an HTML form to pass to JavaScript?
Is this correct? My script takes two arguments one from textbox, one from the dropdown box.
<body>
<form name="valform" action="" method="POST">
Credit Card Validation: <input type="text" id="cctextboxid" name="cctextbox"><br/>
Card Type: <select name="cardtype" id="cardtypeid">
<option value="visa">Visa</option>
<option value="mastercard">MasterCard</option>
<option value="discover">Discover</option>
<option value="amex">Amex</option>
<option value="diners">Diners Club</option>
</select><br/>
<input type="button" name="submit" value="Verify Credit Card" onclick="isValidCreditCard(document.getElementById('cctextboxid').value,document.getElementById('cardtypeid').value)" />
</body>
HTML:
<input type="text" name="name" id="uniqueID" value="value" />
JS:
var nameValue = document.getElementById("uniqueID").value;
If you want to retrieve the form values (such as those that would be sent using an HTTP POST) you can use:
JavaScript
function getData(form) {
var formData = new FormData(form);
// iterate through entries...
for (var pair of formData.entries()) {
console.log(pair[0] + ": " + pair[1]);
}
// ...or output as an object
console.log(Object.fromEntries(formData));
}
document.getElementById("myForm").addEventListener("submit", function (e) {
e.preventDefault();
getData(e.target);
});
Example: https://codepen.io/kevinfarrugia/pen/Wommgd?editors=1111
Alternatively you could use the below less recommended options:
form-serialize (https://code.google.com/archive/p/form-serialize/)
serialize(document.forms[0]);
jQuery
$("form").serializeArray()
I found this the most elegant solution.
function handleSubmit(e) {
e.preventDefault();
const formData = new FormData(e.target);
const formProps = Object.fromEntries(formData);
}
Here is an example from W3Schools:
function myFunction() {
var elements = document.getElementById("myForm").elements;
var obj ={};
for(var i = 0 ; i < elements.length ; i++){
var item = elements.item(i);
obj[item.name] = item.value;
}
document.getElementById("demo").innerHTML = JSON.stringify(obj);
}
The demo can be found here.
document.forms will contain an array of forms on your page. You can loop through these forms to find the specific form you desire.
var form = false;
var length = document.forms.length;
for(var i = 0; i < length; i++) {
if(form.id == "wanted_id") {
form = document.forms[i];
}
}
Each form has an elements array which you can then loop through to find the data that you want. You should also be able to access them by name
var wanted_value = form.someFieldName.value;
jsFunction(wanted_value);
This is a developed example of https://stackoverflow.com/a/41262933/2464828
Consider
<form method="POST" enctype="multipart/form-data" onsubmit="return check(event)">
<input name="formula">
</form>
Let us assume we want to retrieve the input of name formula. This can be done by passing the event in the onsubmit field. We can then use FormData to retrieve the values of this exact form by referencing the SubmitEvent object.
const check = (e) => {
const form = new FormData(e.target);
const formula = form.get("formula");
console.log(formula);
return false
};
The JavaScript code above will then print the value of the input to the console.
If you want to iterate the values, i.e., get all the values, then see https://developer.mozilla.org/en-US/docs/Web/API/FormData#Methods
My 5 cents here, using form.elements which allows you to query each field by it's name, not only by iteration:
const form = document.querySelector('form[name="valform"]');
const ccValidation = form.elements['cctextbox'].value;
const ccType = form.elements['cardtype'].value;
A one liner for ES6
getFormData = (selector) => Object.fromEntries(new FormData(document.querySelector(selector)))
console.log('Output of getFormData:')
console.log(getFormData('#myTargetForm'))
<!DOCTYPE html>
<html>
<body>
<h2>Get Form Data as Javascript Object</h2>
<form id="myTargetForm">
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
Define this function in your Javascript:
getFormData = (selector) => Object.fromEntries(new FormData(document.querySelector(selector)))
Then just call with any selector e.g.:
getFormData('#myTargetForm')
Expanding on Atrur Klesun's idea... you can just access it by its name if you use getElementById to reach the form. In one line:
document.getElementById('form_id').elements['select_name'].value;
I used it like so for radio buttons and worked fine. I guess it's the same here.
This is the answer of your question.
You can pass the values of the form fields to the function by using this.<<name of the field>>.value.
And also changed input submit to button submit. Called the function from form.
<body>
<form name="valform" method="POST" onsubmit="isValidCreditCard(this.cctextbox.value, this.cardtype.value)">
Credit Card Validation: <input type="text" id="cctextboxid" name="cctextbox"><br/>
Card Type:
<select name="cardtype" id="cardtypeid">
...
</select>
<br/>
<button type="submit">Verify Credit Card</button>
</body>
Technically you can do it in your function by using document.getElementById("cctextboxid"). But his solution is concise and simple code.
I know this is an old post but maybe someone down the line can use this.
// use document.form["form-name"] to reference the form
const ccForm = document.forms["ccform"];
// bind the onsubmit property to a function to do some logic
ccForm.onsubmit = function(e) {
// access the desired input through the var we setup
let ccSelection = ccForm.ccselect.value;
console.log(ccSelection);
e.preventDefault();
}
<form name="ccform">
<select name="ccselect">
<option value="card1">Card 1</option>
<option value="card2">Card 2</option>
<option value="card3">Card 3</option>
</select>
<button type="submit">Enter</button>
</form>
Please try to change the code as below:
<form
onSubmit={e => {
e.preventDefault();
e.stopPropagation();
const elements = Array.from(e.currentTarget);
const state = elements.reduce((acc, el) => {
if (el.name) {
acc[el.name] = el.value;
}
return acc;
}, {});
console.log(state); // {test: '123'}
}}
>
<input name='test' value='123' />
</form>
Several easy-to-use form serializers with good documentation.
In order of Github stars,
jquery.serializeJSON
jquery-serialize-object
form2js
form-serialize
<form id='form'>
<input type='text' name='title'>
<input type='text' name='text'>
<input type='email' name='email'>
</form>
const element = document.getElementByID('#form')
const data = new FormData(element)
const form = Array.from(data.entries())
/*
form = [
["title", "a"]
["text", "b"]
["email", "c"]
]
*/
for (const [name, value] of form) {
console.log({ name, value })
/*
{name: "title", value: "a"}
{name: "text", value: "b"}
{name: "email", value: "c"}
*/
}
It's easy with one for-of loop you can get all field values even checkboxes values also.
In your HTML you should bind a handlSubmit() on your forms onsubmit event
<form name="contact_form"
id="contact-form"
class="form-controller"
onsubmit="handleSubmit(event)"
>
in your javascript your code should apply the following logic no matter what name your assigned to your fields.
const handleSubmit = (event)=> {
event.preventDefault();
const formData = new FormData(event.target);
formObj = {};
for (const [fieldName] of formData) {
const fieldValue = formData.getAll(fieldName);
formObj[fieldName] = fieldValue.length == 1 ? fieldValue.toString() : fieldValue
}
console.log('formObj',formObj)
}
Quick solution to serialize a form without any libraries
function serializeIt(form) {
return (
Array.apply(0, form.elements).map(x =>
(
(obj =>
(
x.type == "radio" ||
x.type == "checkbox"
) ?
x.checked ?
obj
:
null
:
obj
)(
{
[x.name]:x.value
}
)
)
).filter(x => x)
);
}
function whenSubmitted(e) {
e.preventDefault()
console.log(
JSON.stringify(
serializeIt(document.forms[0]),
4, 4, 4
)
)
}
<form onsubmit="whenSubmitted(event)">
<input type=text name=hiThere value=nothing>
<input type=radio name=okRadioHere value=nothin>
<input type=radio name=okRadioHere1 value=nothinElse>
<input type=radio name=okRadioHere2 value=nothinStill>
<input type=checkbox name=justAcheckBox value=checkin>
<input type=checkbox name=justAcheckBox1 value=checkin1>
<input type=checkbox name=justAcheckBox2 value=checkin2>
<select name=selectingSomething>
<option value="hiThere">Hi</option>
<option value="hiThere1">Hi1</option>
<option value="hiThere2">Hi2</option>
<option value="hiThere3">Hi3</option>
</select>
<input type=submit value="click me!" name=subd>
</form>
<script>
var inputs = document.getElementById("form_id_here").elements;
for (i = 0; i < inputs.length; i++) {
if (inputs[i].type === "text" || inputs[i].type === "textarea") {
console.log(inputs[i].value); // Get value of input tag which you have entered.
}
}
</script>
Some answers above didn't cater for forms with multiple fields with the same name e.g.multiple <input name="categories[]"> so I made this quickly. It expects field with the same name that you want to collect as an array to end in [] as a convention but could be updated to handle other scenarios.
function getFormValues(form) {
const formData = new FormData(form);
return Array.from(formData.entries()).reduce((prev, [inputName, val]) => {
return {
...prev,
[inputName]: inputName.endsWith('[]')
? prev[inputName]
? [...prev[inputName], val]
: [val]
: val,
};
}, {});
}
// alternative if you don't like reducers and nested ternary statements
function getFormValues(form) {
const formData = new FormData(form);
const values = {};
for (const [inputName, val] of formData.entries()) {
if (inputName.endsWith('[]')) {
values[inputName] = values[inputName] ? [...values[inputName], val] : [val];
} else {
values[inputName] = val;
}
}
return values;
}
// then attach this to form submit
function onSubmit(e) {
e.preventDefault();
const values = getFormValues(e.target);
// etc...
}
values gives something like { "single": "something", "categories[]": ["one", "two"] }
<input type="text" id="note_text" />
let value = document.getElementById("note_text").value;