Looping through object to find input name - javascript

I have a couple of inputs like so:
<input name="education[1][yearbegin]" type="date" class="form-control">
<input name="education[2][yearbegin]" type="date" class="form-control">
The data is sent to my server to be verified, and if it's invalid it sends back data like so:
{
"education.0.institution":["The education.0.institution field is required."],
"education.0.degree":["The education.0.degree field is required."]
}
I don't always get more than 1 back, sometimes it could be many I am trying to loop over to append an error to the input like so:
var errors = $.parseJSON(data.responseText);
alertHtml += '<ul>';
$.each(errors, function (key, value) {
$('.form-control[name=' + key + ']').closest('.form-group').addClass('has-error');
alertHtml += '<li>' + value + '</li>';
});
alertHtml += "</ul>";
This doesn't work though, because it's trying to find the input name of:
education.1.yearbegin
Rather than
education[1]yearbegin
My inputs won't always be arrayed, but the ones that are don't append How can I append the error message to the input by changing the javascript? The json is being sent back by Laravel's array validation

It's unfortunate that the server accepts the names in one form but sends them back in another.
If we assume that dot syntax should always be converted to brackets syntax, it's fairly straightforward to update the keys:
var updated = key.split(".");
if (updated.length == 1) {
updated = updated[0];
} else {
updated = updated[0] + "[" + updated.slice(1).join("][") + "]";
}
For multi-part keys, that inserts [ before the second and ][ in-between the second and third, third and fourth, etc.; and adds ] at the end.
Example:
var errors = [
{"education.1.yearbegin":["The education.1.yearbegin field is required."]},
{"education.2.yearbegin":["The education.2.yearbegin field is required."]}
];
errors.forEach(function(error) {
Object.keys(error).forEach(function(key) {
var updated = key.split(".");
if (updated.length == 1) {
updated = updated[0];
} else {
updated = updated[0] + "[" + updated.slice(1).join("][") + "]";
}
console.log("Original: " + key + ", updated: " + updated);
});
});
If you're also struggling with showing all of the errors in the array next to the form control, you just loop through them. You're receiving an object where the property names in the object are the form control names, and the values are arrays of error messages. So we
Loop through the property names of that object, and for each property name:
Mark the relevant control, and
Loop through that entry's array of errors to append them to alertHtml.
Something long these lines:
var errors = {
"education.1.yearbegin":["The education.1.yearbegin field is required."],
"education.2.yearbegin":["The education.2.yearbegin field is required."]
};
function fixKey(key) {
var updated = key.split(".");
if (updated.length == 1) {
updated = updated[0];
} else {
updated = updated[0] + "[" + updated.slice(1).join("][") + "]";
}
return updated;
}
var alertHtml = '<ul>';
// #1: Loop through the object's property names
Object.keys(errors).forEach(function(key) {
// #2: Mark the control, using the corrected name
$('.form-control[name="' + fixKey(key) + '"]').closest('.form-group').addClass('has-error');
// #3: Loop through the errors
errors[key].forEach(function(msg) {
alertHtml += '<li>' + msg + '</li>';
});
});
alertHtml += "</ul>";
$(document.body).append(alertHtml);
.has-error {
border: 1px solid red;
}
<div class="form-group">
<input name="education[1][yearbegin]" type="date" class="form-control">
</div>
<div class="form-group">
<input name="education[2][yearbegin]" type="date" class="form-control">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

The first issue with the name:
I would just change the name to something that's a bit easier to read rather then having it like:
name="education[1][yearbegin]"
Maybe have it like:
name="EducationYearBegin1"
For the second issue:
You could check if the property is an array, so like this:
if (value instanceof Array) {
value.forEach(function (item) {
alertHtml += '<li>' + item + '</li>';
})
} else {
alertHtml += '<li>' + value + '</li>';
}
Maybe something like that?
The foreach would cover you if you ever had multiple errors in your array too.

You can use String#replace to convert education.1.yearbegin to be education[1][yearbegin]
See fixName function in this code.
function fixName(name) {
var newName = name.replace(/\.\d\./, function ($1) {
return "[" + $1.replace(/\./g, "") + "]"
}).replace(/\].+/, function ($1) {
return $1.replace(/\]/, "][") + "]"
});
return newName;
}
var errors = [{"education.1.yearbegin":["The education.1.yearbegin field is required."]},
{"education.2.yearbegin":["The education.2.yearbegin field is required."]}]; //$.parseJSON(data.responseText);
var alertHtml = document.querySelector("#alert");
alertHtml.innerHTML += '<ul>';
$.each(errors, function (key, obj) {
var realKey = fixName(Object.keys(obj)[0]);
$('.form-control[name="'+ realKey +'"]').addClass('has-error');
alertHtml.innerHTML += '<li>' + obj[Object.keys(obj)[0]][0] + '</li>';
});
alertHtml.innerHTML += "</ul>";
.has-error {
color: red;
}
li {
color: green
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input name="education[1][yearbegin]" type="date" class="form-control">
<input name="education[2][yearbegin]" type="date" class="form-control">
<div id="alert"></div>

Related

Why variable is undefined inside foreach function?

I have this jQuery function were I create a table:
function propertyView(values) {
// build the table
var frame = '<fieldset id = "propertiesValueArea" style="border: solid 1px #6b6b6b;">';
var content = frame + smallHeader + '<table data-role="table" id="propertiesList"><thead><tr></tr></thead>';
$.each($(values), function () {
var data1 = this.RealValue.FieldValue;
var data2 = this.RealValue.Id;
//create tables row
content += '<tr data-id=' + this.Id + '>';
content += '<td style="vertical-align: inherit;text-align:center;"><label for="">' + this.FieldName + '</label></td>';
if (this.FieldValue.indexOf(',') > -1) {
content += '<td style="text-align:center;"><select>';
this.FieldValue.split(',').forEach(function (item) {
if (data1 === item) //Here data1 is undefined!!!
{
content += '<option selected="selected" value="">' + item + '</option>';
}
else {
content += '<option value="">' + item + '</option>';
}
})
content += '</select></td>';
}
else {
content += '<td style="text-align:center;"><input type="text" id="propFieldName" data-id="' + this.Id + '" value="' + congiValue(this.FieldValue, this.RealValue) + '"/>';
}
content += '</tr>';
});
content += '</table>';
content += '</fieldset>'
return content;
}
Inside outter each function I create 2 variables:
var data1 = this.RealValue.FieldValue;
var data2 = this.RealValue.Id;
I try to create this variable inside inner each:
if (data1 === item) //Here data1 is undefined!!!
But on this row I get this error:
Uncaught ReferenceError: data1 is not defined
Any idea why data1 is undefined?
It can be undefined only because this.RealValue.FieldValue or this.RealValue is undefined
It looks like
var data1 = this.RealValue.FieldValue; //it's value is undefined
this.FieldValue //it's value is undefined
try to
console.log(this.FieldValue)
console.log(data1)
After that you can easily found where you are getting an error and why. Else everything looks fine with your code.
I have encountered similar problem before. It took me several hours to discover the problem. Now that aside there some things which is not clear here.
is the value coming from another function's operation? If
this.RealValue.FieldValue;
is coming from e.g. a result of maybe another function then you would need to use async/await to ensure that the function completes its operation and there is data in this.RealValue.FieldValue before you move on to the next line of code.
Maybe the this.RealValue.FieldValue itself does not have any thing assigned to it outside of the function itself.
In order to help you we would need a complete code. If you think your code is too private then you can go through it by trying what #Negi Rox said earlier.
Put console.log(this.RealValue.FieldValue) at various strategic locations in your code to determine when it was assigned a value.

fill the input type hidden from selected multiple option on jquery

I have a input that have type like this:
<input class="emailSend" name="emailSend" type="hidden">
Then I have a multiple select option like this
<div class="controls">
<select id="email" multiple data-rel="chosen" class="input-xlarge" name="email[]">
<?php
foreach ($atasan as $data) {
echo "<option value='" . $data['email'] . "'>" . $data['email'] . "</option>";
}
?>
</select>
</div>
My problem is, I want to fill that hidden input from the option that selected from multiple select option. So let say, the selected option is 'email1', 'email2', 'email3' then would be affected to hidden type like this 'email1, email2, email3'.
I have try this for 3 hour in jquery and I am stuck. My code is like this.
$("#email").change(function() {
var elements = $("#email option:selected").length;
var input = $(".emailSend");
$(".emailSend").html("");
$.each($("#email option:selected"), function(/*index, element*/) {
input.val(input.val() + $(this).html() + ", ");
if (index < elements - 1) {
//code to remove last comma
//any idea ?
}
});
});
So appreciated for the help...
EDIT Here is the fiddle :JSFIDDLE
Updated FIDDLE now that I see what you meant by looking at the fiddle you made.
this is actually all you need to do...
Updated to include spaces between the addresses!
$("#email").on('change', function() {
var thisval = $(this).val() + '';
var myarr = thisval.split(',');
var newval = '';
myarr.forEach(function(i,v) {
newval += i + ' , ';
});
newval = newval.slice(0, newval.length - 3);
$("#emailsend").val(newval);
});
Commented Version (for learning and stuff)
$("#email").on('change', function() {
//the extra space at the end is to typecast to string
var thisval = $(this).val() + '';
//takes string of comma separated values and puts them
//into an array
var myarr = thisval.split(',');
//Initialize a new string variable and loop through
//the array we just created with MDN's forEach()
var newval = '';
myarr.forEach(function(i,v) {
//add to the string through each iteration,
//including comma with spaces
newval += i + ' , ';
});
//use .slice() to trim three characters off the
//end of the final string. (strip final comma)
newval = newval.slice(0, newval.length - 3);
//and last but not least, assign our newly created
//and properly formatted string to our input element.
$("#emailsend").val(newval);
});

javascript searching a json object

I'm trying to search a value in json
<input type="text" id="test" size="21" maxlength="120">
<button onclick="Zoek()" class="btn btn-info btn-block">
tijdelijke zoek knop
</button>
I'm using this to input a value and the button to call the search function
function Zoek() {
var qeustion = document.getElementById("test").value;
document.getElementById("accordion").innerHTML == "";
var text = '{ "FAQ" : [' +
'{ "vraag":"John" , "antwoord":"Doe" },' +
'{ "vraag":"Anna" , "antwoord":"Smith" },' +
'{ "vraag":"Peter" , "antwoord":"Jones" } ]}';
obj = JSON.parse(text);
for (i = 0; i < text.length; i++) {
if (obj.FAQ[i].vraag == qeustion) //(obj.FAQ[i].getString("vraag").contains(question))
{
document.getElementById("accordion").innerHTML += "<div class='panel panel-default'><div class='panel-heading' role='tab' id='heading" + i + "'><h4 class='panel-title'><a data-toggle='collapse' data-parent='#accordion' href='#" + i + "' aria-expanded='false' aria-controls='" + i + "''>" + obj.FAQ[i].vraag + " </a></h4></div><div id='" + i + "' class='panel-collapse collapse in' role='tabpanel' aria-labelledby='heading" + i + "'><div class='panel-body'> " + obj.FAQ[i].antwoord + "</div></div></div> WOWOWOWOWOWOWOWOWWOWOWOOW";
} else {
document.getElementById("accordion").innerHTML = "No results found"
}
}
}
and this is my search function
so lets say i enter John it goes straigt to the else and doesnt do the if statement even though i am pretty sure it kind of is right
could anyone give me some pointers on searching in a json object? is there a other way to do this?
Please see jsfiddle attached demonstrating what you are looking for and will show you what you need to do - https://jsfiddle.net/vuenume2/1/
It is essential to have a break statement in your loop.
Without the break statement your true value for success simply gets overwritten with false on the next iteration, except for the last possible credentials, for which there is no "next" iteration.
if (obj.FAQ[i].vraag == qeustion)
{
<!-- do stuff -->
break;
} else {
<!-- do other stuff -->
}
Also, if you haven't done so you need to add a div with an id accordion to your html
<div id="accordion"></div>
Use filter function. You parsed in obj that string into json so You could do:
var target = obj.FAQ.filter(function(element){ return element.vraag == qeustion})[0];
if(target == undefined) {
// there is no that object logic
} else {
// there is that object logic
}

JSON - how to parse it?

I just got a problem about this response. Supposedly if I want to choose item from the response it must be an array value.
"telegraphicTransferBankMap": {
"BOA BEJ, JKT": "0330301",
"BPD KALBAR SYARIAH, PTK": "1239922",
"ANDARA, DPSR": "4660019",
"GANESHA HAYAM WURUK, JKT": "1610017",
...
}
Actually must be like this one right? (let me know if I'm mistaken)
"telegraphicTransferBankMap": [
{"BOA BEJ, JKT": "0330301"},
{"BPD KALBAR SYARIAH, PTK": "1239922"},
{"ANDARA, DPSR": "4660019"},
{"GANESHA HAYAM WURUK, JKT": "1610017"},
...
]
My code:
var ul = $('#telegraphicTransferBankMap');
var html ='';
for (var key in telegraphicTransferBankMap) {
if (telegraphicTransferBankMap.hasOwnProperty(key)) {
telegraphicTransferBankMapItem = telegraphicTransferBankMap[key];
html += '<option value="'+telegraphicTransferBankMapItem.xxxxxx+'">'+telegraphicTransferBankMapItem.yyyyyyy+'</option>';
}
}
ul.append(html);
Then I want to put telegraphicTransferBankMapItem.xxxxxx as bankId and telegraphicTransferBankMapItem.yyyyyyy as bankName.
Use your first json and change your loop like,
var telegraphicTransferBankMap = {
"BOA BEJ, JKT": "0330301",
"BPD KALBAR SYARIAH, PTK": "1239922",
"ANDARA, DPSR": "4660019",
"GANESHA HAYAM WURUK, JKT": "1610017",
}
for (var key in telegraphicTransferBankMap) {
if (telegraphicTransferBankMap.hasOwnProperty(key)) {
bank = telegraphicTransferBankMap[key];
html += '<option value="' + bank + '">' + key + '</option>';
}
}
Live Demo
Also you should bank-id as key in your json rather than of bank name.
As of your code here:
if (telegraphicTransferBankMap.hasOwnProperty(key)) {
telegraphicTransferBankMapItem = telegraphicTransferBankMap[key];
an object like your first definition is expected - and sufficient
To add that to the option list just do
html += '<option value="'+key+'">'+telegraphicTransferBankMapItem+'</option>';

Jquery reading input field that was created from JSON loop

I cannot figure out for the life of me why this will not work. I am trying to pull the value of a textfield that was created with a loop from a json file.
In this code, at the very bottom I just do a simple click(function() {alert()} just to see if I can pull a value and its returning undefined. But if I remove '#name' and put in 'input' it captures it, but only for the first of several input fields.
Any help is really appreciated
JSON
{
"Controls": [{
"Button":[{ "Name":"Button", "x": "1","y": "2","width": "3","height": "4","Transition":"" }],
"Image":[{"x": "5","y": "6","width": "7","height": "8"}],
"TextField":[{"x": "9","y": "10","width": "11","height": "12","Rows":""}]
}]
}
The Code(there is soome getJSON stuff above this)
//Slide In Attributes Panel Based on Selected Object
$(document).on('click', '#code li', function () {
var index = $('#code li').index(this);
var selected = $(this).text();
switch (selected) {
case selected:
$('#options').hide();
hidePanels();
$('#temp').remove();
$('#objectAttributes').show("slide", 200);
break;
//If it does work show what variable is being used
default:
alert(selected);
break;
}
//Shows Selected LI Index
$('#codeIndex').text("That was div index #" + index);
//Pull list of Attributes for selected Object
$.getJSON('controls.json', function (data) {
//Build Attributes List
var attributeList = '<div id="temp">';
//Target based on selected object
var target = selected;
attributeList += '<div>' + target + '<div>';
$.each(data.Controls[0][target][0], function (kk, vv) {
attributeList += '<div style="float:right">' + kk + ':' + '<input type="text" id='+ kk + '>' + '</input>' + '</div>';
});
attributeList += '</div></div>';
attributeList += '</div>';
$('#objectAttributes').append(attributeList);
$('#temp').append('<div id="editIndex">'+"Modifying index" + " " +index+'</div>');
$(document).on('click', '#saveAttributes', function () {
var $x = $('#name').val();
alert($x);
})
});
});
Ok, so after a little hacking around with a jsfiddle the answer turned out to be a lot simpler than I first thought. Ever since HTML 4.01 class names and IDs have been case sensitive (reference), which means that your selector $('#name') wasn't matching the JSON Name.
So a simple change, such as in this simplified jsfiddle seems to work as desired. Hopefully this helps!

Categories

Resources