Im fairly new to javascript and im trying to find an object of an array i created by the configID property. I used the method find() for this.
JS Code:
var configurationArray = flow.get("configurationArray") || [];
var configurationId = msg.topic.split("/")[1];
var configuration = {
configID: this.configurationID,
configurationModules: this.MSGesture.payload
};
if(!configurationArray.find(x => x.configID == this, configurationId)){
configurationArray.push(this.configuration);
} else {
//to do
}
I am using node-red which gives me flow and msg.
The Error i get:
Cannot read property 'configId' of undefined
Any help is appreciated
You could destructure the property and add a default object.
Then take some instead of find, because you need only the check.
At last, omit this and take directly the value.
if (!configurationArray.some(({ configID } = {}) => configID === configurationId)) {
configurationArray.push(this.configuration);
} else {
//to do
}
If you like to have an abstract callback, you could take a closure over configurationId, like
const hasId = id => ({ configID } = {}) => configID === id;
if (!configurationArray.some(hasId(configurationId)) {
configurationArray.push(this.configuration);
} else {
//to do
}
Related
Please help,
I want to make a method findChildByIdInData(data:any, childId:string) where the data is any JSON main node that has children with Ids.
Simply, how to make a method that receives JsonNode and its child Id as parameters to find that object using angular.
In my case, I have a data as a node where I want to find its children's objects (may be nested) by id.
Thanks for your time :)
To implement lodash
https://stackoverflow.com/a/41992126/18762612
import { get } from "lodash";
variable in component
deepObj = {a:{b:{n:{e:100, c: 120}}}
example of get
constructor(){
get(deepObj, 'a.b.n.e');
}
Got the result by using the Recursively Traverse an Object method:
this link helps me: https://cheatcode.co/tutorials/how-to-recursively-traverse-an-object-with-javascript.
the backendService:
// Verify the object
isObject(value): any {
return !!(value && typeof value === "object");
};
// Find object in node
findNestedObject(object: {}, keyToMatch: String, valueToMatch: String): any {
if (this.isObject(object)) {
let entries = Object.entries(object);
for (let i = 0; i < entries.length; i += 1) {
const [objectKey, objectValue] = entries[i];
if (objectKey === keyToMatch && objectValue === valueToMatch) {
return object;
}
if (this.isObject(objectValue)) {
let child = this.findNestedObject(objectValue, keyToMatch, valueToMatch);
if (child !== null) {
return child;
}
}
}
}
return null;
};
and call that method in component as:
// Find the nested object by passing node, key, & value
// the this.shop is your backend data or json
let result = this.backendService.findNestedObject(this.data, "id", "dataId");
console.log("Result: ", result);
I'm trying to create an object that returns the property name for any property that was accessed. Is this possible to do cleanly in javascript / nodejs? This is what I would like to accomplish:
const mirror = {/*...*/};
console.log(mirror[1]);
// => 1
console.log(mirror.123);
// => '123'
console.log(mirror.randomPropertyHere);
// => 'randomPropertyHere'
I can overwrite a getter for a specific property, but I don't know how to do it generically. Also how can I differentiate between a number and a string?
My (not working) attempts
const mirror = {
get[1] () {
console.log('number');
return 1;
},
get['1'] () {
console.log('string');
return '1';
}
};
console.log(mirror[1]);
console.log(mirror['1']);
Very much appreciate your time and help!
With a proxy.
const mirror = new Proxy({}, {
get(_, prop) { return prop; }
});
console.log(mirror[1]);
// => 1
console.log(mirror['123']);
// => '123'
console.log(mirror.randomPropertyHere);
// => 'randomPropertyHere'
Also how can I differentiate between a number and a string?
Can't, object properties have to be strings or symbols.
I want to make this code prettier with recursion.
findModel = function(oldModel, ...modelStyles) {
let model = oldModel.elements;
let i = 0;
try {
do {
model = model.children.find(child => child.mStyle === modelStyles[i]);
i += 1;
} while (i < modelStyles.length);
return model;
} catch (e) {
return undefined;
}
};
tried this:
findModel = function(oldModel, ...modelStyles) {
let model = oldModel.elements;
let i = 0;
if (i < modelStyles.length) {
model = model.children.find(child => child.mStyle === modelStyles[i]);
i += 1;
return model;
} else {
return undefined;
}
};
but it's still not working well. in the first code I get only the element, in the second one I get also undefined.
What did I wrong?
As amply noted in comments, you are actually never calling the function recursively.
When it comes to "pretty", I would not go for recursion, but for reduce:
var findModel = function(oldModel, ...modelStyles) {
try {
return modelStyles.reduce((model, style) => model.children.find(child => child.mStyle === style), oldModel.elements);
} catch (e) {} // No need to explicitly return undefined. It is the default
};
If you really need recursion, then first realise that your function expects a first argument type that never occurs again. Only the toplevel model has an elements property, so you can only call this function for ... the top level of your hierarchy.
To make it work, you would need another function that takes the model type as it occurs in the children:
var findModel = function(oldModel, ...modelStyles) {
function recur(model, style, ...modelStyles) {
if (style === undefined) return model;
return recur(model.children.find(child => child.mStyle === style), ...modelStyles);
}
// Need to change the type of the first argument:
try {
return recur(oldModel.elements, ...modelStyles);
} catch (e) {}
};
If you would change the code where the function is called initially, you could of course pass mainmodel.elements instead of mainmodel, so that this type difference problem is resolved. If you can make that change, then the recursive function can become:
var findModel = function(model, style, ...modelStyles) {
if (style === undefined) return model;
try {
return recur(model.children.find(child => child.mStyle === style), ...modelStyles);
} catch (e) {}
};
Still, I would prefer the reduce variant.
The point of recursive function is to call themselves into themselves. In your case, you are calling the function once, but the function never call itself so it just go through once. I'm not sure of the context so I can't fix your code but i can give you an example of recursion.
Lets say we have an object with property. Some are string, some are number and some are objects. If you want to retrieve each key of this object you would need recursion, since you don't know how deep the object goes.
let objectToParse = {
id: 10,
title: 'test',
parent: {
id: 5,
title: 'parent',
someKey: 3,
parent: {
id: 1,
title: 'grand-parent',
parent: null,
someOtherkey: 43
}
}
};
function parseParentKey(object) {
let returnedKey = [];
let ObjectKeys = Object.keys(object);
for(let i = 0; i < ObjectKeys.length; i++) {
if(typeof object[ObjectKeys[i]] === "object" && object[ObjectKeys[i]] !== null) {
// we are calling the methode inside itself because
//the current property is an object.
returnedKey = returnedKey.concat(parseParentKey(object[ObjectKeys[i]]));
}
returnedKey.push(ObjectKeys[i]);
}
return returnedKey;
}
console.log(parseParentKey(objectToParse));
I know this does not answer your question but it gives you a hint on how to use recursion properly. If your first code works, I don't see why you would need to change it in the first place.
I'm looking for a way to reference an object, based on a variable with it's name in it.
I know I can do this for properties and sub properties:
var req = {body: {jobID: 12}};
console.log(req.body.jobID); //12
var subProperty = "jobID";
console.log(req.body[subProperty ]); //12
var property = "body";
console.log(req[property][subProperty]); //12
is it possible for the object itself?
var req = {body: {jobID: 12}};
var object = "req";
var property = "body";
var subProperty = "jobID";
console.log([object][property][subProperty]); //12
or
console.log(this[object][property][subProperty]); //12
Note: I'm doing this in node.js not a browser.
Here is an exert from the function:
if(action.render){
res.render(action.render,renderData);
}else if(action.redirect){
if(action.redirect.args){
var args = action.redirect.args;
res.redirect(action.redirect.path+req[args[0]][args[1]]);
}else{
res.redirect(action.redirect.path);
}
}
I could work around it by changing it to this, but I was looking for something more dynamic.
if(action.render){
res.render(action.render,renderData);
}else if(action.redirect){
if(action.redirect.args){
var args = action.redirect.args;
if(args[0]==="req"){
res.redirect(action.redirect.path+req[args[1]][args[2]]);
}else if(args[0]==="rows"){
rows.redirect(action.redirect.path+rows[args[1]][args[2]]);
}
}else{
res.redirect(action.redirect.path);
}
}
Normally it's impossible to reference an object by its name. But since you have only two possible candidates...
var args, redirect_path = '';
if(args = action.redirect.args) {
try {
redirect_path = ({req:req,rows:rows})[args[0]][args[1]][args[2]];
} catch (_error) {}
}
res.redirect(action.redirect.path + (redirect_path || ''));
I'm using inline object {req:req,rows:rows} as a dictionary to lookup for args[0] value.
I wrapped the whole construction with try ... catch, because it's dangerous. For example, passing anything except 'req' or 'rows' as args[0] will result in an exception being thrown.
I also moved res.redirect outside of if to clarify the code.
Update
It's also possible to use args array with arbitrary length. But to do so you'll need to loop through args array:
var branch, redirect_path;
if (action.redirect.args) {
try {
branch = { req: req, rows: rows }
action.redirect.args.forEach(function(key) {
branch = branch[key];
});
if ('string' === typeof branch) {
redirect_path = branch;
}
} catch (_error) {}
}
res.redirect(action.redirect.path + (redirect_path || ''));
A added 'string' === typeof branch check to ensure that the resulting value is a string.
Here is the line which is causing null or not an object error
if(frm.elements["hdn_retain"+indexval].value==""){
....
} else {
....
}
frm.elements["hdn_retain"+indexval] may be a null object. So, it will have error when getting the value. You can check the frm.elements["hdn_retain"+indexval] if it is null first.
if(frm.elements["hdn_retain"+indexval] != null && frm.elements["hdn_retain"+indexval].value=="")
Either frm or frm.elements["hdn_retain"+indexval] isn't a valid object (doesn't exist in the dom) and therefore you can't access it's property.
you could try something like:
if(frm.elements["hdn_retain"+indexval] && frm.elements["hdn_retain"+indexval].value==""){
Following is the result of alert statement:
alert("frm:::"+frm);
alert("frm elements::::"+frm.elements);
alert("frm hdn_retain :: "+frm.elements["hdn_retain"+indexval]);
frm:::[object]
frm elements::::[object]
frm hdn_retain :: undefined
you can use this utility method getProperty i always use to make sure i get a nested namespace back without worrying about whether or not something is defined:
function getProperty(ns, obj) {
var nsArray = ns.split('.'),
i = 0,
nsLen = nsArray.length;
while (nsLen > 0) {
var newNs = nsArray.shift();
if (obj[newNs]) {
obj = obj[newNs];
} else {
return false;
}
nsLen = nsArray.length;
}
return obj;
};
var index = "hdn_retain" + indexval;
// the following `value` will come back as a valid object/value or a false
value = getProperty('elements.' + index + '.value', frm);
if (value) {
// do whatever
} else {
// do not whatever
}
this can be applied not only to this situation but to any other situation you need to make sure a certain namespace is available before usage.