Converting checkboxes to JSON array - javascript

I'm trying to serialize checkboxes on a form where several checkboxes will have the same name.
<input name="mycheckbox" type="checkbox" value="A"/>A</br>
<input name="mycheckbox" type="checkbox" value="B"/>B</br>
Using the serializeArray such as below everything works great. If both A & B are checked the JSON.stringify correctly represents the JSON as an array:
{"mycheckbox":["A","B"]}
However if I only have A checked the JSON is no longer represented as an array:
{"mycheckbox":"A"}
In my RESTful backend that's processing I need to consistently pass as an array. Is there any way of forcing stringify to represent it as an array?
var jsonData = JSON.stringify($('form').serializeObject());
$.fn.serializeObject = function () {
var o = {};
var a = this.serializeArray();
$.each(a, function () {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};

You'll have to find each element within the form by name and check whether it's a checkbox.
But note that it's perfectly valid to have multiple text boxes, passwords, file uploads, etc. as well. Nothing defines a form input as being "multiple" in any way except the presence of two successful controls with the same name when you happen to look at the form.
It might be easier to just deal with this on the backend when you know you need an array. Or submit the form with plain old form encoding rather than JSON, and let your backend's HTTP library deal with it. (Most of them let you do something like request.GET.getall('mycheckbox') to always get a list back.)

If you do not want to modify the plugin's code directly, you can simply modify the object afterward.
var formData = $('form').serializeObject(),
mycheckboxVal = formData.mycheckbox;
if (!$.isArray(mycheckboxval)) {
formData.mycheckbox = [mycheckboxval];
}
//then you serialize
var jsonData = JSON.stringify(formData);
You could also perform the same logic server-side if you prefer.

Related

jQuery detect input change

I'm working on a feature where the user needs to be informed that there are unsaved changes in a form in case if they decide to navigate away from the page.
I am almost done but there's a tiny problem-
I am setting a boolean dirty on input change event.
The .change() event will detect any kind of change, as in it doesn't keep track of changes. For example, if an input field has the original value hello, which is modified to bye and back to hello, it will still set the dirty boolean.
Is there any way where I can take a backup of the form with initial values and then compare it with itself at every change event?
You need a way to serialize the form data into a JSON object, and then you could either compare the JSON object by iterating the properties or by comparing the JSON.stringify values.
I have slightly modified the method of objectifying the form data from here in order to do this.
var form = document.getElementById("myForm");
var originalFormData = objectifyForm(form);
var originalFormDataString = JSON.stringify(originalFormData);
setInterval(function() {
var formData = objectifyForm(form);
var formDataString = JSON.stringify(formData);
console.log("Form is dirty: " + (formDataString != originalFormDataString));
},1000);
function objectifyForm(formArray) {//serialize data function
var returnArray = {};
for (var i = 0; i < formArray.length; i++){
returnArray[formArray[i]['id']] = formArray[i]['value'];
}
return returnArray;
}
<form id="myForm">
<input id="myInput" value="test" type="text" />
</form>
You can do something like this. Remember this solution is just a sample. You have multiple input element, than use array/object to save there defaultValue.
var defaultValue = document.getElementById("myText").defaultValue;//Get the default value
var handleChange = function (){
let value = document.getElementById("myText").value;//get the current value
if(defaultValue===value){
console.log("dirty false")
}else {
console.log("Dirty True")
}
}
<input type="text" id="myText" value="abc" onkeyup="handleChange()">
I think you can create a javascript empty initial_values = {} object. initialised it with the default values in the form of key:value pairs. and if dirty boolean is set, it can be used to compare later on.

Getting value of selected checkbox with jquery from checkboxes without id's

I have a number of checkboxes that are generated from a JavaScript API call from a database. I need to be able to pass the values of the checkboxes which are then selected by the user, and sent to the processing page. The issue is that the checkboxes don't have ID's associated with them(or this wouldn't be a problem) They all have the same name, but no ID's.
What is the best way to find which check boxes are selected, and pass their values to the following page?
One way I started was with an array:
var options = ["option1","option2","option3"];
var option 1 = [0];
var option 2 = [1];
var option 3 = [2];
On the processing page, using:
var option1 = getFromRequest('option1') || '';
var option2 = getFromRequest('option2') || '';
var option3 = getFromRequest('option3') || '';
Is there a better way of doing this?
I've changed the implementation to the following:
var values = []
$("input:checkbox.subIndustry").each(function(){
values.push(this.value);
});
passing the values to the success page with
window.location.href = REGISTER_SUCCESS +'&values='values.join(",")
which should then get the value with
var variablname = getFromRequest('values') || "";
This is returning Undefined. Any help?
An easy way to select them would be something like $("input[type=checkbox]:checked")
However, if you wanted to keep up with them as they are checked, even if they are added after you load, you could create a variable, then asign a delegation to the "change" state of each input that is a checkbox and update this variable on each change.
It's as simple as:
var checked, checkedValues = new Array();
$(function() {
$(document).on("change", "input[type=checkbox]", function(e) {
checked = $("input[type=checkbox]:checked");
// if you wanted to get an array of values of the checked elements
checkedValues = checked.map(function(i) { return $(this).val() }).get();
// make a string of the values as simple as joining an array!
var str = checkedValues.join(); // would return something like: value1,value2,ext...
});
})
Working Example
Since all your checkboxes have the same name, you can retrieve the checked ones using a variation of:
var checked = $('input[name=ckboxname]:checked');
see: :checked selector for more information
you can simply get the values of checked checkboxes by using
$('input[name=checkboxname]:checked').val();
this will give you the value of checkbox which is checked and for all values simply use
each function of jquery.
Turns out, the answer was to utilize indexOf in the underscore.js library. The solution had to be applied in the API being used to send data.
(_.indexOf(values, '9') != -1 ? 1 : '0'),

Javascript Form: Only Changed Fields

I have a php-site with a form on which i output preselected values via php. On form submit I want to check which values have changed and just submit these via javascript.
These are the preselected values I passed over from php. It's important that I keep the associative array structure.
var pbData = jQuery.parseJSON("{
"GameMode":"DEATHMATCH",
"Current Map":"VEGAS JUNKYARD",
"Current Missions":["VEGAS JUNKYARD","VILLA","PRESIDIO","KILL HOUSE","MURDERTOWN","CQB TRAINING","STREETS","THREE KINGDOMS CASINO","IMPORT\/EXPORT;"],
"RoundDuration":"3 minutes"}");
I marked the error in the code.
<script>
function displayVars(){
var form = document.getElementById('settings');
var elems = form.elements;
var txt = "";
for (var index = 0; index < elems.length; index++){
var selIndex = elems[index].selectedIndex;
if (typeof selIndex !== "undefined"){
//the Index Name in the json-object and the name of the form-field are the same
var idxName = elems[index].name;
//HERE is the problem. I want to access the subobject via a variablename, so i can iterate through it, but that doesnt work.
console.log ("pbData default = "+pbData.idxName); //always undefined
if (elems[index].value !== pbData.idx_name){
//building a POST-Url
txt = txt + elems[index].name + "=" + elems[index].options[selIndex].value+"&";
}
}
}
console.log (txt);
return false;
}
</script>
I know that I could do this differently, also with jQuery. In my case as I have the preselected values as a php-variable in any case, i think it's easier like this.
I would really like to know how I can iterate through the subobjects via a variable that contains the object names.
This is due to how you'e trying to access the property of the (JSON) object. Consider
var o1 = {idxName: true},
o2 = {foo : 'bar'},
idxName = 'foo';
o1.idxName; // true
o2.idxName; // undefined
o2[idxName]; // 'bar'
You need to access the property via pbData[idxName].
Additionally, you're not escaping quotes in your JSON string, and line breaks need to be escaped as follows
var pbData = jQuery.parseJSON("{\
\"GameMode\":\"DEATHMATCH\",\
\"Current Map\":\"VEGAS JUNKYARD\",\
\"Current Missions\":[\"VEGAS JUNKYARD\",\"VILLA\",\"PRESIDIO\",\"KILL HOUSE\",\"MURDERTOWN\",\"CQB TRAINING\",\"STREETS\",\"THREE KINGDOMS CASINO\",\"IMPORT\/EXPORT;\"],\
\"RoundDuration\":\"3 minutes\"}");
In Javascript you could keep an object or array with initial values and only post those values that are changed.
But in fact, I would do something similar, but in PHP. You can keep the original values in the session and compare the posted values to those initial values to see what has changed. That way, you won't depend on Javascript. Not only may Javascript be disabled, but also, a fast user may theoretically post the form before the Javascript has run. To move this check to PHP eliminates that risk.

Get all Radio Button and Text Field values

I have a form on my page that is located in a class .class-lesson. The form itself only contains text field and radio buttons. I do not know how many of each are in the form since it is dynamically generated by PHP. Each new input in the form is named q1, q2, ... qn.
I am trying to get all the values, whether answered or not, and stored into a javascript array. This is my code so far:
// get the value of each input field
var numQuestions = $(".class-lesson label").not(".csubmit").length;
// store each answer
for (var i = 0; i < numQuestions; i++) {
// store our variables
var tempAnswer = undefined;
var tempReference = $(":input[name=q"+(i+1)+"]");
// loop through each item
if ( tempReference.attr('type') == 'radio' ) tempAnswer = $(":input[name=q"+(i+1)+"]:checked").val();
else tempAnswer = tempReference.val();
// output / store the item
alert( tempAnswer );
}
I am sure there has to be an easier way to do this but I don't know. This is why I am asking. If I don't have the :checked then it will just grab the first value of the radio group.
So, how can I make this more efficient?
To get an entire <form> (or any set of inputs) in serialized form, as it would be if submitted to the server normally (without any JavaScript involved), use .serialize(), like this:
var formData = $(".class-lesson :input").serialize();
//or...
var formData = $("#formID").serialize();
If you're submitting via AJAX for example this makes your code incredibly simple, for example:
$.post("test.php", $("#formID").serialize(), function(data) {
alert("Response was: " + data);
});

javascript/jQuery: how do you dynamically turn attribute values into object keys? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert form data to JS object with jQuery
Here is my problem, I have a whole bunch of elements that look like this...
<input type="email" id="email" data-item="email" data-key="contact_details"/>
<input type="tel" id="mobileNo" data-item="mobileNo" data-key="contact_details"/>
<input type="text" id="sleeve_length" data-item="sleeve_length" data-key="measurements"/>
<input type="text" id="inseam" data-item="inseam" data-key="measurements"/>
Each element has a 'data-key' and 'data-item' which corresponds to the json form i'm trying to turn them into, which will look something like this...
{
"measurements" : {"sleeve_length" : value, "inseam" : value},
When each data-item is unique... and like this when it isn't...
"contact_details" : [
{"email" : value, "mobileNo" : value},
{"email" : value, "mobileNo" : value}
]
}
Now because my web app involves many forms, I need a way to dynamically transform the markup above into these json strings... but I can't seem to wrap my head around it!
Does anyone have any idea how I can approach this?
Something like so:
var json = {};
$('#path .to input').each(function(e) {
var key = $(this).attr('data-key');
var param = $(this).attr('data-item');
var obj = {};
obj[param] = $(this).val();
// If we already have a record...
if(key in json) {
// If it's not an array, make it an array
if(typeof(json[key].push) != 'function')
json[key] = [ json[key] ];
// Toss it on the pile
json[key].push(obj);
} else {
// There's only 1 thus far, keep it k/v
json[key] = obj;
}
});
etc. Fairly basic, the key points just being testing whether or not the key you're working with exists or not, and if so, converting it to an array.
Edit: this is untested, but it should work.
Edit 2: revised code so your hash key vars don't come across as strings.
You could let some JS MVC / MVVC library do this for you. For example, Knockout. I haven't used it myself yet, but from a glance it seems neat. You define mapping between your JSON object and HTML form fields, and the library would monitor form fields and update the JSON object (a "view model").
Something like:
var myJson = {};
// jQuery
$('input').each(function () {
myJson[$(this).attr('data-key')][$(this).attr('data-value')] = $(this).val();
});
// Native JS
var els = document.getElementsByTagName('input');
for (var i = 0, l = els.length; i < l; i += 1) {
myJson[els[i]['data-key']][els[i]['data-value']] = els[i].value;
}
Should do the trick. It loops through all of the input elements on the page and puts the data found in each element into an object with the key data-key and sets that equal to an object with the key data-value and the value the value of the input element.
Helpful?
Edit: Is that better? I don't know what I was thinking.

Categories

Resources