Access object property - javascript

How i can select the count(user) from the tab object?
var tab =
[
{ id: '1', 'count(user)': 11 },
{ id: '2', 'count(user)': 31 },
{ id: '3', 'count(user)': 3 }
]
This prints 2:
console.log(tab[1].id)
but this gives me an error:
console.log(tab[1].count(user))
ReferenceError: user is not defined
How can I fix this?

Like this:
alert(tab[1]["count(user)"]);
Here is an example: JSFiddle
By the way, while the JSON in your example technically works, it is not formatted in a "best practice" way. Parameter names should have quotes around them:
{ 'id': '1',...
And parameter names should be valid JavaScript variables names, ie., no parenthesis, brackets, etc. This would be a more acceptable name:
'count_user': 11
Then you would not have had an issue using
console.log(tab[1].count_user)

Related

Javascript Joi Alternatives Array or Array of Objects

I'm confused about Joi alternatives. I can't figure out how the alternatives are invoked against the item to tb validated.
function validateCourse(course) {
const objectSchema = {
id: Joi.number().required(),
name: Joi.string().min(3).required()
};
const arraySchema = Joi.array().items(Joi.object(objectSchema)).required();
return Joi.alternatives(objectSchema, arraySchema).validate(course);
}
This works for the object but not for the array of objects.
[
{
"id": 10,
"name": "XY"
},
{
"id": 11,
"name": "JFK"
}
]
I'm not sure if my array schema is at fault or my use of alternatives?
It appears it is working! However the invalidation message returned by the Joi when validating an array is vague when compared to validating the object.
validating object : "name" length must be at least 3 characters long
validating array : "value" must be an object
Which is not completely useful as now I have to potentially check hundreds of items to find the one at fault.
But that's a different issue consider this closed!
There is nothing wrong with your schema. The error you are getting with the array is:
"value" must be an object, "value" at position 0 fails because
[child "name" fails because ["name" length must be at least 3 characters long]]
Which is right, your name key must have at least 3 characters.
And, as you asked, you can get the object(s) that failed from the error description or
you can also use any.error(err) in order to keep track of those objects.
For instance, if you want to know the array indexes that failed you can do:
const arraySchema = Joi.array().items(Joi.object(objectSchema)).required().error((errors) => {
const indexes = errors.map((err) => err.path[0]);
return new Error(`Indexes with error: ${indexes}`)
})
For this array of objects:
[
{
'id': 11,
'name': 'ABC'
},
{
'id': 22,
'name': 'ABC'
},
{
'id': 33,
'name': 'XY'
},
{
'id': 44,
'name': 'ABC'
},
{
'id': 55,
'name': 'XY'
},
]
The error will be:
Indexes with error: 2,4
You can access your error message by doing:
validationResult.error.message
Don't forget to use { abortEarly: false } in your validation:
Joi.alternatives(objectSchema, arraySchema).validate(course, { abortEarly: false })
Worked as described for arrays but then displayed nothing for non arrays so I made a small change :
const arraySchema =
Joi.array().items(Joi.object(objectSchema)).required().error((errors) =>
{
if (errors[0].path.length)
{
const indexes = errors.map((err) => err.path[0]);
if (indexes.length) return new Error(`Indexes with error: ${indexes}`);
}
return errors;
});
So if it's an array I return the array of bad indexes (as you suggested). But if it's an object I just return { errors } unchanged.

JS - conditional property selection

I have two arrays with the following structure:
First dictionary:
[{id: 111, abbr: "FBI", name: "Federal Burreau of Investigation"},
{id: 59, abbr: "CIA", name: "Central Intelligence Agency"},
{id: 130, abbr: "EU", name: "European Union"}]
Second dictionary:
[{id: 28, name: "Administration"},
{id: 107, name: "Advocacy"},
{id: 100, name: "Agriculture"},
{id: 77, name: "Air & Aviation"}]
I am trying to create a delimiter function that accesses these objects in the following way:
finalDictionary.push({ delimiter: dictionary[0].abbr.charAt(0) });
and correspondingly:
finalDictionary.push({ delimiter: dictionary[i].name.charAt(0) });
My aim is to make the method universal and diminish the amount of final code. As you see, the only difference here is the property by which I am accessing the dictionary, 'abbr' and 'name'. I tried to do it the following way:
var ext = (name === 'agencies') ? 'abbr' : 'name';
finalDictionary.push({ delimiter: dictionary[i].ext.charAt(0) });
However, I get an error:
TypeError: Cannot read property 'charAt' of undefined
The question is how can I conditionally access the object property? Maybe, there is a better approach than this one? If not, what am I doing wrong?
The problem is in this line:
dictionary[i].ext.charAt(0)
dictionary[i].ext assume that you have a property ext inside dictionary[i] which you don't and therefore it returns undefined.
than what happens is undefined.charAt(0) which raises your error
Change it to:
dictionary[i][ext].charAt(0)
Than the property here is the value of ext which is 'abbr' or 'name'
There is no property named ext in the example json you have shown, that is why you are facing this error.

Javascript Property with three dots (...)

I have a problem with code I am supposed to work with. I found a syntax I am not familiar with and I have trouble googling the documentation:
export const Something = class Something {
constructor(someObject = {}) {
this.someObject = {...Something.someObjectDefaultAsStaticMethod,...someThing};
};
// The rest of the class
};
I have problems understanding what the three dots (...) in front of the parameter do. And "dots in parameter javascript" is a bad search term. Can someone help me, maybe tell me what this syntax is actually called or just directly link me to documentation?
That is not ES6 but has only been added in ECMAScript 2018.
It is called "Object Rest/Spread Properties" and is part of the Spread Syntax.
... (three dots in Javascript) is called the Spread Syntax or Spread Operator. This allows an iterable such as an array expression or string to be expanded or an object expression to be expanded wherever placed.
I want to list down the mostly used practical Use Cases of the Spread Syntax (Spread Operator). The following has been explained with examples in this stackoverflow answer.
Combine Arrays (Concatenate Arrays)
Copying Arrays
Calling Functions without Apply
Destructuring Arrays
Function Arguments as Rest Parameters
Using Math Functions
Combining Two Objects
Separate a String into Separate Characters
The [...something] is the spread operator. It in essence allows for an array or string to be expanded. You will see it used often in React, but has many other use cases.
MDN has great documentation on the spread operator:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
You can use "..." in an object. In this example below, "...data" gets 'name: "John", age: 24':
const data= { name: "John", age: 24 };
const newData = {
...data, // Here
sex: "Male"
}
console.log(newData);
This is the result:
{ name: "John", age: 24, sex: "Male" }
This is other example with "...data[key]" to add "id" to each object in an array:
const data = [
{ name: "John", age: 24 },
{ name: "Marry", age: 18 },
{ name: "Tom", age: 15 },
]
const newData = [];
for(const key in data) {
const obj = {
id: Number(key),
...data[key] // Here
}
newData.push(obj);
}
console.log(newData);
This is the result:
[
{ id: 0, name: "John", age: 24 },
{ id: 1, name: 'Marry', age: 18 },
{ id: 2, name: 'Tom', age: 15 }
]
Context: One of the use cases is to do a "copy", but you should take care of this particular "by reference" behavior when working with sub-properties.
Finding: Take care that sub-properties are NOT passed by value, but by reference. In other words, only first level properties are passed as a copy "by value". See the example:
sourcePerson = { name: 'John', colors: ["red", "blue"] }
targetPerson = { ...sourcePerson }
console.log("Target person result:\n", JSON.stringify(targetPerson), "\n\n") //it seems a copy, but...
console.log("Let's update the name source value:\n")
sourcePerson.name = 'Kevin'
console.log("Updated source person:\n", JSON.stringify(sourcePerson), "\n")
console.log("Target person is NOT updated, It keeps a copy by value\n")
console.log(JSON.stringify(targetPerson), "\n\n")
//But if you update a sub-property, it has NOT been copied by value
console.log("Let's update a color sub-property:\n")
sourcePerson.colors[0] = "YELLOW"
console.log("Updated source person:\n", JSON.stringify(sourcePerson), "\n")
console.log("Target person is updated BY REFERENCE!\n")
console.log(JSON.stringify(targetPerson)) // it is not a copy, it is a reference!
console.log("\nCONCLUSION: ... spread syntax make a copy 'by value' for first level properties, but 'by reference' for sub-properties, so take care!\n")

What is the format of Express' req.params?

I've got a weird thing I'm running into with req.params while working with Express. It works fine for calling the subordinate properties - e.g.: res.json(req.params.paramName); gives me the desired paramName value. But when I tried to pass the entire res.params object to the client via res.json(req.params), I just get an empty array [] in the browser instead of the JSON object I was expecting. (res.send gives the same result.)
Looking a bit deeper, I dumped req.params to the console:
console.dir(req.params);
and got this:
[ creator: '1', timeStart: '2', timeEnd: '3', dateDensity: '4' ]
wut? Is that even syntactically possible in Javascript?
If req.params is a simple object like the Express code and documentation indicate, I should be getting:
{ creator: '1', timeStart: '2', timeEnd: '3', dateDensity: '4' }
An array like what I'm getting above should even be possible, should it?
I did some sanity checks and passed a couple of test objects to the console as well:
console.dir([{foo:1}, {arr:2}, {gog:3}, {blah:4}]);
console.dir({foo:1, arr:2, gog:3, blah:4});
and the console dump gives me:
[ { foo: 1 }, { arr: 2 }, { gog: 3 }, { blah: 4 } ]
{ foo: 1, arr: 2, gog: 3, blah: 4 }
So console.dir is working OK.
Lastly, I hardcoded a:
res.json({foo:1, arr:2, gog:3, blah:4});
into my Express code and the browser dutifully gives me:
{
"foo": 1,
"arr": 2,
"gog": 3,
"blah": 4
}
Am I smoking crack here? What is going on with req.params?
That's how v8 prints out arrays with string keys:
var myArr = [];
myArr.key = "oops";
Remember, [] instanceof Object is true.
req.params is an array, suggesting the possibility of positional params.

Passing hash data to javascript

I have a nested hash I've created from a previous question of mine Nested group query in Rails
The hash now being:
{14=>{11=>{21=>7, 22=>8}, 4=>{21=>7, 22=>4}}, 16=>{5=>{25=>2, 26=>1}, 11=>{26=>2, 25=>5}} }
I want to pass this data to javascript and I think it will be best to have key names for each attribute/model like so:
{ question_id: 14=>{ club_id: 11=>{ choice_id: 21=>7, choice_id: 22=>8} etc etc}
My question is, would this be a best practice to pass data in Rails to Javascript or would it be better to do this from a json variable from the controller.
If the approach I'm trying is fine, is there a way to set key names in a hash as my attribute names from my initial query?
Answer.where(:question_id => 14).group(:club_id, :choice_id).count
Thanks
There is no structure like that:
{ question_id: 14 => { club_id: 11 => { choice_id: 21 => 7, choice_id: 22 => 8 }
You're trying to associate a hash value with further values, which is an invalid structure. One way to achieve a semantic structure (meaning a structure which reflects the actual relationships of your counts and id's to each other) for your data so you can pass it to the browser via JSON would be to build a hash like the following:
{ questions: [
{
id: 14,
clubs: [
{
id: 11,
choices: [
{
id: 21,
count: 7
},
{
id: 22,
count: 8
}
]
}
]
}
]
}

Categories