How to parse two-dimensional checkbox name into JSON with matching indices? - javascript

One of our clients' sites has a form that we hijack and submit via AJAX. Recently we got a request to have it support a fluid list of checkboxes with predefined indices in the name - and I'm a little stumped as to how to properly parse this into an array.
Here's an example:
<li><input type="checkbox" name="group[69][4096]" /> Thin</li>
<li><input type="checkbox" name="group[69][8192]" /> Oily</li>
<li><input type="checkbox" name="group[69][16384]" /> Dry</li>
The first- and second-level indices are going to change on a regular basis, so they can't be hard-coded. How can I create a two-dimensional javascript array and place these values under the same keys?
For obvious reasons I don't want to use eval(), and I tried my hand at regex but I'm afraid it isn't my strong suit. I got close - .+\[([0-9]+)\]\[([0-9]+)\] will match the string on http://regexr.com/ - but it doesn't seem to work in js for some reason. At least, I can't get it to return the captured groups.

You could reduce the inputs into a 2d array by parsing each input's name with this regexp /group\[(\d*?)\]\[(\d*?)\]/:
const inputs = Array.from(document.querySelectorAll('[name^="group"]'));
const grid = inputs.reduce((grid, input) => {
const [, y, x] = input.name.match(/group\[(\d*?)\]\[(\d*?)\]/);
grid[y] = grid[y] || [];
grid[y][x] = input.value;
return grid;
}, []);
console.log(grid);
<input name="group[0][0]" value="0,0"/>
<input name="group[0][1]" value="0,1"/>
<input name="group[0][2]" value="0,2"/>
<input name="group[0][3]" value="0,3"/>
<input name="group[0][4]" value="0,4"/>
<input name="group[1][0]" value="1,0"/>
<input name="group[1][1]" value="1,1"/>
<input name="group[1][2]" value="1,2"/>
<input name="group[1][3]" value="1,3"/>
<input name="group[1][4]" value="1,4"/>
<input name="group[2][0]" value="2,0"/>
<input name="group[2][1]" value="2,1"/>
<input name="group[2][2]" value="2,2"/>
<input name="group[2][3]" value="2,3"/>
<input name="group[2][4]" value="2,4"/>

Related

What is the best way of getting the values that will be typed at dynamically generated inputs

I've got a form that creates inputs dynamically.
An example of it would be something like this:
<form>
<input name="item[0][name]">
<input name="item[1][name]">
</form>
The 0 and 1 being the id of the item.
Note that the 0 and 1 could be 15 and 49, or even 520, 854 and 2.
There's no order neither ordination and, there is also no limit for being only two items.
The question is:
"What is the best way of getting the values that will be typed at those inputs, before sending them to the backend?"
The only way I can think of is adding ids when generating the form, but that doesn't seem elegant at all.
If you cant figure a better way, that would be lovely =)
You can use document.querySelectorAll() and Attribute Selector
function submit() {
let inputs = document.querySelectorAll('input[name*=item]');
let values = Array.from(inputs).map(({value})=>value);
console.log(values);
}
<form>
<input name="item[0][name]">
<input name="item[1][name]">
</form>
<button onclick="submit()">Sumbit</button>
Try
function submit() {
let inputs = document.querySelectorAll('input');
let values = [...inputs].map(x=>x.value);
console.log(values);
}
<form>
<input name="item[0][name]">
<input name="item[1][name]">
</form>
<button onclick="submit()">Send</button>
You could use the HTMLFormElement.elements property.
const formInputs = document.getElementById('a-form').elements
const dataObject = {}
for (let i = 0; i < formInputs.length; i++) {
dataObject[formInputs[i].name] = formInputs[i].value
}
console.log(dataObject)
<form id="a-form">
<input type="text" name="item[0][name]" />
<input type="text" name="item[1][name]" />
<input type="text" name="item[2][name]" />
</form>
Set a specific data attribute (for instance data-my-input) on them, then use querySelectorAll(‘input[data-my-input]’) to get them all and send them to your backend.

how to push object ino an array when user inputs value in angularJs

I have multiple input fields under different headings:-
<label>User</label>
<input type="text" ng-model="a.arr.username" name="arr[0]"/>
<input type="text" ng-model="a.arr.userdob" name="arr[0]"/>
<input type="text" ng-model="a.arr.userpanNo" name="arr[0]"/>
<label>Employee</label>
<input type="text" ng-model="a.arr.empname" name="arr[1]"/>
<input type="text" ng-model="a.arr.empdob" name="arr[1]"/>
<input type="text" ng-model="a.arr.emppanNo" name="arr[1]"/>
<label>Daily Workers</label>
<input type="text" ng-model="a.arr.dwname" name="arr[2]"/>
<input type="text" ng-model="a.arr.dwdob" name="arr[2]"/>
<input type="text" ng-model="a.arr.dwpanNo" name="arr[2]"/>
I want to save above data in the format:- [{a.arr.username:any value},{a.arr.empname:any value},{a.arr.dwname:any value}]. But the structure I am getting is:- {a.arr.username:any value,a.arr.empname:any value,a.arr.dwname:any value}.
Is there any way to do this?
Where you are storing data you will have to store it like :
a.arr=[];
//here you have to define object for each index before making keys of it.
a.arr[i]={};
Try this
var arr=[]; arr.push({'a.arr.username':$scope.a.arr.username,{'a.arr.empname':$scope.a.arr.empname}})
Basically, you want to make your object as an array of it's properties. I suggest you to leave the code as it is and just add a code to make another controller property which will hold the array of those properties.
To get the array of properties, below code will help you:
var x = {username: "any value", empname: "any value", dwname: "any value"};
var newArr = [];
var properties = Object.keys(x);
for(var i=0;i<properties.length;i++){
newArr.push({});
newArr[newArr.length - 1][properties[i]] = x[properties[i]];
};
Let me know if you need to understand anything else regarding this.
Best Regards

User input from text box and radio buttons reiterated in an alert, showing undefined? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Basically what I'm attempting to do is a mad lib story with user input. I've gotten to the stage where I need to show an alert with each input, alert("hello "+name+". You've chosen "+userinput+", etc)
My alert is showing up, but the information is not collecting from the textboxes/radio buttons. It is simply showing undefined.
This is what I have so far..
The purpose of this step is to add the code to the new function so that it will create our story.
Add JavaScript statements to your function to collect all the information from each form element.
Display the user’s information in one alert function.
For Example: ”Hello [name], your story values are [title], [vegetable], [adjective], [number #1], [number #2]”
function beginstory() {
alert("welcome "+name+". you have chosen: "+title+" "+hobby+" "+adjective+" "+number1+" ");
var name=(document.getElementById('username').value);
var title = document.getElementById("storytitle").value;
var hobby = document.getElementById("hobby").value;
var adjective = document.getElementById("adjective").value;
var number1 = document.getElementById("number1").value;
var number2 = document.getElementById("number2").value;
var trex = document.getElementById("trex").value;
var steg = document.getElementById("steg").value;
var diplod = document.getElementById("diplod").value;
var crazy = document.getElementById("crazy").value;
var charming = document.getElementById("charming").value;
var curious = document.getElementById("curious").value;
var he = document.getElementById("he").value;
var she = document.getElementById("she").value;
var ze = document.getElementById("ze").value;
var jurassic = document.getElementById("jurassic").value;
var colonial = document.getElementById("colonial").value;
var twenty = document.getElementById("twenty").value;}
<form id="story" action="">
What is your name? <input type="text" name="storyelements" id="username"><br>
What is the title of your story? <input type="text" name="storyelements" id="storytitle"><br>
Name a hobby: <input type="text" name="storyelements" id="hobby"><br>
Name an adjective trait: <input type="text" name="storyelements" id="adjective"><br>
Name a number greater than one: <input type="text" name="storyelements" id="number1"><br>
Name another number greater than one: <input type="text" name="storyelements" id="number2"><br>
Choose a dinosaur: <input type="radio" name="dinosaur" id="trex" checked="checked">Tyrannosaurus Rex
<input type="radio" name="dinosaur" id="steg">Stegosaurus
<input type="radio" name="dinosaur" id="diplod">Diplodocus<br>
Choose a personality trait: <input type="radio" name="trait" id="crazy" checked="checked">Crazy
<input type="radio" name="trait" id="charming">Charming
<input type="radio" name="trait" id="curious">Curious<br>
Choose your preferred pronoun: <input type="radio" name="pronoun" id="he" checked="checked">He
<input type="radio" name="pronoun" id="she">She
<input type="radio" name="pronoun" id="ze">Ze<br>
Choose an era: <input type="radio" name="era" id="jurassic" checked="checked">Jurassic
<input type="radio" name="era" id="colonial">Colonial
<input type="radio" name="era" id="twenty">The 1920s<br>
<!-- BUTTONS -->
<input type="button" onclick="beginstory()" name="storytime" value="Start Your Story!"></button><br>
<input type="reset" name="clearform" value="Clear Form">
</form>
Well, you might try defining the variables BEFORE you display them.
As is, you are trying this:
alert("welcome "+name+". you have chosen: "+title+" "+hobby+" "+adjective+" "+number1+" ");
var name=(document.getElementById('username').value);
var title = document.getElementById("storytitle").value;
...
See how you are telling it to display, for example, 'name'... and then in the very next line telling it what name should mean?
Try flipping that around.
...
var colonial = document.getElementById("colonial").value;
var twenty = document.getElementById("twenty").value;}
alert("welcome "+name+". you have chosen: "+title+" "+hobby+" "+adjective+" "+number1+" ");
By putting the alert at the end of the function instead of the beginning, you have defined the variables, and THEN told it where to display them.
Should work better for ya.
** EXPANDED **
OK... to grab the buttons that get selected:
All form elements will have a name or an id. These are used to pass information to the server in name=value pairs whenever the form is submitted.
Most people prefer id for most things, but on radio buttons specifically, you should have a name set; this allows you to have two or more buttons return their value under the same identifier:
<label>Male<input type="radio" name="gender" value="male"></label>
<label>Female<input type="radio" name="gender" value="female"></label>
That doesn't work with id's because id's need to be unique.
You can then create a variable and load it with the radio button itself:
var myButton = document.getElementByName('gender');
This returns BOTH radio buttons, because they both have the same name. It return them in an array, and to access them, you simply use array notation:
var maleButton = myButton[0]; // These are stored in the order they are found in
var femaleButton = myButton[1];// in the HTML
NOTE: document.getElementById('youridhere') returns a single value instead of an array, since id's are always unique... but we can't use it here, since these are not using id's.
You can then access the members of these objects just like you would any other:
alert("The value of maleButton is " + maleButton.value);
Should alert "male".
If that was the only data you needed out of the object, you could have grabbed that originally, however, and saved some typing:
var myValue = document.getElementByName('gender')[0].value;
Hope that helps!

Pass Array HTML Element(s) in JavaScript

I have array of checkboxes like below,
<input type="checkbox" value="1" id="a_r_id[1]" name="a_r_id[1]">
<input type="checkbox" value="1" id="a_r_id[2]" name="a_r_id[2]">
<input type="checkbox" value="1" id="a_r_id[3]" name="a_r_id[3]">
<input type="checkbox" value="1" id="a_r_id[4]" name="a_r_id[4]">
in my page... and i want to submit only the checked one via JavaScript (jQuery AJAX)... how can i do that ?
EDITED :
Actually, i want to get all array keys on the checked checkbox so that i can post it via ajax. Something like "1,4" as a string.
var keys = [],
keystring;
$('input[name^="a_r_id"]:checked').each(function () {
keys.push($(this).attr('name').replace(/a_r_id\[(\d+)\]/, '$1'));
});
keystring = keys.join();
Of course, there are better ways of doing this, but this answers your question as you've framed it.
Finally, i found an answer for my question above. I'll write it down right here.
Problem :
how can i get "key" from array HTML element(s) ? (in my case, only checked checkbox i want to get)
my answer code is something like this :
//first, i get every checked checkbox using jQuery selector,
//as mentioned by DerekHenderson.
var list_agent = $('input[name^="a_r_id"]:checked');
var l_c_agent = new Array();
//then, i create a loop to loop each object returned.
for(var i=0;i<list_agent.length;i++){
//after that, i'm using Regular Expression ( match() ) on every returned object id and throw it into some array.
l_c_agent[i] = list_agent[i].id.match(/[0-9]+/);
}
//finally, i join the array using javascript join() method so that i can pass it using jQuery AJAX as a string to my controller and process it.
var clean_agent_list = l_c_agent.join();
var add_url = 'test.php';
$.ajax({
url: add_url,
type: "GET",
data : { 'list_agent' : clean_agent_list },
success: function(data_return) {
//alert(data_return);
}
});
the output will be something like this (if using my example question above and we're check element with id 1,3 and 4 only)
1,3,4
if anybody have a better code, please write it here so that we can discuss which is better to solve my problem.
The method you want seems a bit backwards; the browser will already submit only the checked checkboxes, but here goes:
var re = /\[(\d+)\]$/,
numbers = [];
$('input[name^="a_r_id\\["]:checked').each(function() {
numbers.push(+this.name.match(re)[1]);
});
console.log(numbers.join(','));
It selects all checked boxes whose name starts with "a_r_id[". Then, a regular expression is used to extract the number portion between square brackets and added to the list of values.
I think you want to do something like this
<input type="checkbox" value="1" id="a_r_id_1" name="a_r_id[]">
<input type="checkbox" value="2" id="a_r_id_2" name="a_r_id[]">
<input type="checkbox" value="3" id="a_r_id_3" name="a_r_id[]">
<input type="checkbox" value="4" id="a_r_id_4" name="a_r_id[]">
Radio Buttons seems to be more applicable here rather than checkboxes try this:
<input type="radio" name="radiogroup" value="1" id="a_r_id[1]" name="a_r_id[1]">
<input type="radio" name="radiogroup" value="2" id="a_r_id[2]" name="a_r_id[2]">
<input type="radio" name="radiogroup" value="3" id="a_r_id[3]" name="a_r_id[3]">
You can get the selected value using
$("input:radio[name=radiogroup]").click(function() {
var value = $(this).val();
//
do something with var
//
});

JS syntax for checkbox name attribute with square brackets

This function limits the number of checkboxes selected by the user, but I'm having trouble getting it to work when the name attribute has square brackets (i.e. name=baz[]).
For some reason I can't get this code to work in jsfiddle, but it's based on this tutorial, which has a working demo.
function chkcontrol(j) {
var total = 0;
for (var i = 0; i < document.form1.baz.length; i++) {
if (document.form1.baz[i].checked) {
total = total + 1;
}
if (total > 3) {
alert("Please select up to three choices")
document.form1.baz[j].checked = false;
return false;
}
}
}
<form name="form1">
<input type=checkbox name="baz[]" value="1" onclick="chkcontrol(0);">Item 1
<input type=checkbox name="baz[]" value="2" onclick="chkcontrol(1);">Item 2
<input type=checkbox name="baz[]" value="3" onclick="chkcontrol(2);">Item 3
<input type=checkbox name="baz[]" value="4" onclick="chkcontrol(3);">Item 4
<input type=checkbox name="baz[]" value="5" onclick="chkcontrol(4);">Item 5
<input type=submit value="submit">
</form>
Chaya, your issue is actually stemming from the fact that "[]" is part of the name.
While there are provisions to turn forms and their named elements into JS-accessible objects automatically, there are no provisions to understand which elements are intended to be arrays, versus non-arrays, as that's a server-side distinction: ?baz[]=1&baz[]=2.
If you were to ask for form1["baz[]"]; you should get a list of all elements named "baz[]".
From there, if you were to say form1["baz[]"][0]; you should get the first element named "baz[]".
You can, of course, write some parsing magic to automatically find all elements with "[]" in their names and append the "baz" as an array of the form, filled with all elements named "baz[]". And at that point you could do exactly what you were looking to do, before.
Whether or not that's overkill depends on what you're doing.
But simply writing form1["baz[]"][i] in your loop shouldn't be much more time-consuming than what you've currently got.

Categories

Resources