form.serializeArray() converts each element into string - javascript

Trying to form.serializeArray() and passing serialized data to the server.
Problem: This method also converts boolean and integer to string. And on server side on the basis of the
value , I am trying to get the data type because of which it gives me String everytime.
Actual Output:
[Object { name="para1", value="1"}, Object { name="para2", value="2"}, Object { name="para3", value="true"}, Object { name="para4", value="rep1"}]
Required Output:
[Object { name="para1", value=1}, Object { name="para2", value=2}, Object { name="para3", value=true}, Object { name="para4", value="rep1"}]
Please suggest the solution for this.

You could process the value string of each object and create a new array with converted values. For example, the strings true and false would be converted to their respective boolean value and numbers would be converted to integers. Note that my example below is quite simple and doesn't cover all possibilities (floats are also converted to integers).
Edit: As noted by #sanfor in the comments, every string containing an integer is converted to an integer value, although strings like "123" could also be treated as strings. However, given the information in the question that the type of the input is unknown, this method provides the desired results.
JSFiddle (open the console to see the output):
var values = [
{
name: 'para1',
value: '1'
},
{
name: 'para2',
value: 'true'
},
{
name: 'para3',
value: 'this is a string'
}
];
var result = values.map(function(obj) {
var value;
if (obj.value === 'true') {
value = true;
} else if (obj.value === 'false') {
value = false;
} else if (!isNaN(obj.value)) {
value = parseInt(obj.value);
} else {
value = obj.value;
}
return {
name: obj.name,
value: value
};
});
console.log(result);

As #Vohuman already mentioned, the values are strings as intended. To make them something else you would need to either use some other function to achieve it, or handle the output of the serializeArray afterwards.
More likely solution is to teach your back-end to resolve the type based on the field. You usually know what you are expecting on back-end so you also know the type required and based on that you can (try) to cast it to be correct type.

Related

Converting string to a type (node.js)

I know this seems like an odd problem, but at the moment I'm creating a webserver to save data to a mongodb database using mongoose. To use that, I need to create a model with a schema which basically defines the values I can search to, as well as the type they should be (String, Number, etc.)
As I said before, since it's a webserver, I'd like to make it so the webserver will create the model and the schema, with a body object in the request. However, there is an issue. I can only pass the type (String, Number, etc.) as a string. I've come up with a solution to parse the value into a type, that being the code below
getTypeByString: function (string) {
if (string == 'String') {
return String
}
if (string == 'Number') {
return Number
}
if (string == 'Array') {
return Array
}
if (string == 'Object') {
return Object
}
}
However, I feel like there is probably a more simple solution. If there is or isn't, please let me know! I'd like to release my code on GitHub eventually, and I'd like it to be as dynamic and simple as possible. Thank you in advance
String, Number, Array and Object are also properties of the global variable (or window variable if you are in a browser).
You can check it yourself by evaluating:
global['String'] === String // true
For this reason, you can just use the string to lookup the type within the global object, and return it:
getTypeByString: function (string) {
if (['String', 'Number', 'Array', 'Object'].includes(string)) // be sure that you are actually returning a type
return global[string];
return null;
In regards to getting a defined type from a string you can use an object to define the types and use the string as the key.
const DefinedTypes = {
String: String,
Number: Number,
Array: Array,
Object: Object,
CustomType: classOfCustomType
};
Using it.
const typeAsString = 'String';
const type = DefinedTypes[typeAsString];
You could use a switch statement to make the code a bit simpler:
getTypeByString: function(stype){
switch(stype){
case "String": return String;
case "Number": return Number;
case "Array": return Array;
case "Object" : return Object;
default: return null; // or throw an error
};
};

Destructuring one or many return types from a function ES6

I am using a library (Yup) that normally puts errors as key-value pairs, where the values are strings into an object, for me to read and display to the user. The strings are simply error keys for a table lookup of pretty error messages.
console.log(errors)
// output
{
required: "form:error:required"
}
I have written some custom functions so that, for certain error keys, I will now return an object looking like:
console.log(errors)
// output
{
minChars: {key: "form:error:minChars", options: {count: 2} }
}
I am using i18next where I need to pass a translation key like so:
t(key, options)
Currently, I have some very ugly code that fetches the translation key from the errors object but then it could be an simple string, or an object with key and options.
My current code to do so is:
const errorObj = isError ? _.get(errors, field.name, '') : ''
let errorKey, errorOptions
if (typeof errorObj === 'string') {
errorKey = errorObj
} else {
errorKey = errorObj.key
errorOptions = errorObj.options
}
Without this ugly type-checking, is there no clever destructuring I can do to handle multiple return types?
I have tried returning an array instead of an object, but then I run into the issue of a string being indistinguishable from an array.
Am I missing something simple here?

JS: weird object comparison behavior

Given this code:
const name = { name: 'amy' };
function greet(person) {
if (person == { name: 'amy' }) {
return 'hey amy';
} else {
return 'hey there';
}
}
console.log(
greet(name) // 'hey amy'
);
console.log(
greet({ name:'amy' }) // 'hey there'
);
console.log(name == { name: 'amy' }); // true
console.log(name === { name: 'amy' }); // false
console.log(Object.is(name, { name: 'amy' })); // false
Why does double-equals comparison return true when using the name variable, but not an object literal?
First, I thought that maybe it's because the objects have the same memory address, but as one can see it's not true.
Moreover, if we turn things upside-down and define the variable inside the function, the comparison returns false! (It is not shown in the code but you can check it out)
I'm seriously confused and will appreciate the explanation.
EDIT:
Here is where I have tested the code. Nodejs and browser console in Chrome give me the regular results, how it should be. So maybe it is something about the interpreter.
The problem here is the use of the word name for your variable.
In a browser, the window object has a name property that must always be a string. If you try to assign something to it that is not a string, it will be converted to one.
Then, when you compare an object with a string, the object will also be converted and the two strings compared. This is why you see it sometimes return true. Example:
// This will end up being assigned to window.name, and will be converted to a string.
var name = {name: "amy"}
console.log(name) // [object Object]
// Then, when you compare that to another object using ==, the object will also be converted to string.
console.log(name == {name: "amy"}) // true, because the string [object Object] is equal to itself.
Change the name of the variable to anything else, or use let or const, and the problem should disappear:
// This will end up being assigned to window.other, but isn't converted to string
var other = {name: "amy"}
console.log(other) // {"name": "amy"}
// Now, both are objects, and unless they are the exact same object, comparing two objects is always false.
console.log(other == {name: "amy"}) // false, no two distinct objects are ever equal
// Using let will not assign this variable to window.
let name = {name: "amy"}
console.log(name) // {"name": "amy"}
// Again, now we compare two distict objects, which always results in false.
console.log(name == {name: "amy"}) // false
You assume that Javascript will perform the comparision with == as you are thinking of it in your mind, but it is not. But as this is a custom object you can't expect Javascript to hand you a custom implementation out of the box. You should implement it yourself.
The only case where this would work is when you use the === operator to check whether the object are the same but by their memory address, thus skipping any custom-object-data-based comparison whatsoever.

jQuery - Get value from JSON Stringify

I have a form, that I need to get the values from:
var formConfig = JSON.stringify($("#bookingform").serializeArray());
which returns below:
[{"name":"client_id","value":"1"},{"name":"consignee_id","value":""},{"name":"client","value":"DAKO"},{"name":"model","value":"2"},{"name":"type","value":"2"},{"name":"temperatur","value":"2"},{"name":"shipper_labels","value":"1"},{"name":"batteri_labels","value":"1"},{"name":"batteri_number","value":"2222"},{"name":"pickup","value":"April 27, 2017 18:25"},{"name":"intern_marks","value":"fdsfads"},{"name":"extern_marks","value":"sadsfdsf"},{"name":"consignee","value":""},{"name":"marks","value":""}]
I then need to access above values from the JSON string, which I am using this function to:
var confirmBooking = function(element, setting, correct, notcorrect) {
$('.confirm-booking')
.find(element)
.html(setting === 1 ? correct : notcorrect);
};
The thought is, I can use above function:
confirmBooking('.config_batteri', formConfig.client_id, "Yes", "No");
and so on..
formConfig.client_id should return 1, since that's the value in the JSON string above.
However it returns undefined:
console.log(formConfig.client_id); // Returns "undefined"
You need to use JSON.parse(), to make it a regular JavaScript object again.
What JSON.stringify() does is, as the name implies, make it a string. That is just a regular string, that represents JSON data. It doesn't magically have the JSON data properties.
Furthermore serializeArray() returns an array of {name: ..., value: ...} objects. If you didn't turn it into a JSON string, the result still could not easily be accessed by doing formConfig.client_id. You'd have to loop through the formConfig array, to find the desired name/value pair.
From the looks of it, you don't need to turn the JavaScript object into JSON at all, if you are just going to use it in the same script (unless you are going to send the JSON string somewhere else perhaps).
Based on OP's comments, I'm assuming OP just want to access a particular form element's value. Using jQuery, this can easily be accomplished with:
// get the value of the client_id element (assuming it's an input element)
var client_id = $( '#bookingform input[name="client_id"]' ).val();
// call the function
confirmBooking( '.config_batteri', client_id, "Yes", "No" );
If you want to have an object with all the form values, have a look at the answers in this question.
Do this:
var jsonStr = '[{"name":"client_id","value":"1"},
{"name":"consignee_id","value":""},
{"name":"client","value":"DAKO"},
{"name":"model","value":"2"},
{"name":"type","value":"2"},
{"name":"temperatur","value":"2"},
{"name":"shipper_labels","value":"1"},
{"name":"batteri_labels","value":"1"},
{"name":"batteri_number","value":"2222"},
{"name":"pickup","value":"April 27, 2017 18:25"},
{"name":"intern_marks","value":"fdsfads"},
{"name":"extern_marks","value":"sadsfdsf"},
{"name":"consignee","value":""},
{"name":"marks","value":""}]';
var obj = JSON.parse(jsonStr);
var val = obj[0].value;
The reason you can't do obj[0].name is because your parsed JSON object has a collection of objects, where the first object has this structure:
{
name:"client_id",
value:"1"
}
So, you have to access it using obj[0].value NOT obj[0].name as it would give you client_id.
I think that's what you want.
console.log(formConfig.confirmBooking);
would change of syntax help? please try
console.log(formConfig[0]['client_id']);
I hope it works for you
Since it's an array of objects, you target the first element which returns an object and then use the "value" property to get the actual value of 1 which you expected .
Also use parseInt("1") to get 1 as a type "number"
Hope this solves the issue ! Let me no ASAP
== EDIT
var formConfig = [{
"name": "client_id",
"value": "1"
}, {
"name": "consignee_id",
"value": ""
}, {
"name": "client",
"value": "DAKO"
}];
// This function returns the value for the name
function search(str) {
for (var obj of formConfig) {
if (obj.name == str) {
return obj.value;
}
}
}
search("client_id"); // 1
search("client"); // DAKO

JSON key is called "true", unable to reference in JavaScript(JSfiddle example)

First of all, I converted a Plist(XML formatted) to JSON with some online tool, this isn't the problem. I managed to pick the important values from this rather big JSON file. With this important information I am rebuilding a new JSON file that is very lean and contains information I can use for a plug-in — that I will create later.
The plist conversion to JSON is ugly. At some point <true/> and <false/> are converted to JSON, leaving this in the JSON: "false":"", or "true":"",.
I am using jQuery
check JSfiddle for an example jsfiddle example
or here
// Simplified (not really a JSON file, but this will do it for explaining)
var themeJSON = {
"item": {
"false": "",
},
};
// I need to know if its enabled: "true" or disabled: "false"
// function for checking if this is the default option
function checkDefault() {
// true is a keyword!
if (themeJSON.item.true) {
return "1";
// so is false!
} else(themeJSON.item.false) {
return "0";
}
}
Maybe I use some other function such as find() ?
updated for answer:
thanks to the comments, this is what I have now:
function checkDefault() {
if (item.hasOwnProperty("true")) {
return "1";
} else if(item.hasOwnProperty("false")) {
return "0";
}
}
Try using the property name as a string:
if (themeJSON.item['true']) {
return '1';
}
else if (themeJSON.item['false']) {
return "0";
}
edit — a comment correctly points out that though accessing the properties by string value will indeed work, your code is otherwise flawed. If the properties are really being given empty string values, then what you really need is a way to test whether the property is there at all, and not (as this code does) just check the value of the property:
if (typeof themeJSON.item['true'] !== 'undefined') { ... }
or, alternatively:
if ('true' in themeJSON.item) { ... }
An explicit check for equality against the empty string would do too:
if (themeJSON.item['true'] === '') { ... }
When an object property has a name which is a reserved keyword, the array index notation can be used to reference it.
A way of checking whether item has a property named false:
> themeJSON.item.hasOwnProperty("false");
true
This not ideal because a single object could have both a false property and a true property.
In JS, foo.bar is the equivalent of foo['bar']. Therefose:
if (themeJSON.item['true'] === "")
Note the need for === as false == "" but false !== "".
Also, I must nitpick. themeJSON is no longer JSON since it's not a string - it's just another JavaScript object. You shouldn't confuse those two.
Try this code
function checkDefault() {
// true is a keyword!
if ("true" in themeJSON.item) {
return "1";
// so is false!
} else if ("false" in themeJSON.item) {
return "0";
}
}

Categories