Best way to reset all values in an Javascript object - javascript

My javascript object looks something like:
$scope.display = {
current: {
key1: 'value1',
key2: ['a', 'b'],
key3: 'value2'
}
}
Upon some events in my code, I would like to reset these values to undefined like below:
$scope.display = {
current: {
key1: undefined,
key2: [],
key3: undefined
}
}
I use libraries like lodash, however i don't see any function that would perform this.
I know how to do this manually, but I was wondering if there is a "Best practices" way of performing this task.

I would create a helper function returning object structure:
function getDisplayObject() {
return {
current: {
key1: undefined, // or you can omit undefined keys
key2: [],
key3: undefined
}
};
}
$scope.display = getDisplayObject();
So later when you need to reset data you would execute $scope.display = getDisplayObject(); again.

Here is my solution with lodash mapValues function:
var $clearObject = function(value) {
if (_.isString(value)) {
return undefined
};
if (_.isArray(value)) {
return [];
};
};
var $scopeDisplay = {
current: {
key1: 'value1',
key2: ['a', 'b'],
key3: 'value2'
}
};
$scopeDisplay.current = _.mapValues($scopeDisplay.current, $clearObject);
console.log($scopeDisplay);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>

You would loop the properties of your object like this
for (var key in current){
if (current.hasOwnProperty(key)){
if (typeof current[key] === 'string'){
current[key] = undefined;
} else if (current[key] instanceof Array) {
current[key] = [];
} // else ??? Not sure how you want to handle other types
}
}
Array check subject to some potential problems described in the comments here

What about this?
// If you just want to reset a simple object
let reset = (obj) => {
Object.keys(obj).map(key => {
if (obj[key] instanceof Array) obj[key] = []
else obj[key] = undefined
})
}
// If you want to reset a complex object
let recursiveReset = (obj) => {
Object.keys(obj).map(key => {
// Test if it's an Object
if (obj[key] === Object(obj[key])) {
recursiveReset(obj[key])
return
}
if (obj[key] instanceof Array) obj[key] = []
else obj[key] = undefined
})
}
// So you can simply use
reset($scope.display.current)
// or
recursiveReset($scope.display)
test link

In my Angular controller, I do the following:
$scope.user = {
firstname: "",
lastname: "",
displayname: "",
email: "",
password: "",
passwordConfirm: ""
};
// default state of the form
$scope.default = angular.copy($scope.user);
/**
* Resets the form to its default state
* #return {void}
*/
$scope.reset = function () {
$scope.user = angular.copy($scope.default);
}
Initially the scope is empty, so I clone it, and whenever it needs reset, simply call a function. However, without knowing the scope of your project, it's hard to determine the best way to handle it.

I did it in AngularJS controller as:
function item_object() {
var list_item = {
ID: '',
Title: '',
LastName: '',
Contact: '',
City: ''
};
return list_item;
}
//Define the object for the item
$scope.Item = item_object();
// Reset product details
$scope.clear = function () {
$scope.Item = item_object();
}
In this way you do not keep a copy of empty or default object. So no extra cost.

There is no built in way. You would need to loop through and set the defaults based on type.
var x = {
current: {
key1: 'value1',
key2: ['a', 'b'],
key3: 'value2'
}
};
_(x.current).forEach(
function(value, key, obj) {
var result = undefined;
if (_.isArray(value)) {
result = [];
}
obj[key] = result;
}
);
console.log(x);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
Basic idea if you have nested objects
var x = {
current: {
key1: 'value1',
key2: ['a', 'b'],
key3: 'value2',
xxxx: {
keyx1: 'valuex1',
keyx2: ['xa', 'xb'],
keyx3: 'valuex2'
}
}
};
function resetObj (obj) {
_(obj).forEach(
function(value, key, objRef) {
var result = undefined;
if (_.isObject(value)) {
resetObj(objRef[key]);
} else {
if (_.isArray(value)) {
result = [];
}
objRef[key] = result;
}
}
);
}
resetObj(x)
console.log(x);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>

If you are using Jquery, like it seems you are doing, you can do that:
Preapre an empty template of your object:
var emptyTemplate = {
current: {
key1: undefined,
key2: [],
key3: undefined
}
}
and then run:
$scope.display = $.extend(true, {}, emptyTemplate);
If you want to automate it, define some data binding:
var defaults = {
String: undefined,
Array: [],
bool: false
}
Then loop in your object, like other suggestions:
function resetObj (obj) {
_(obj).forEach(
function(value, key, objRef) {
if (_.isObject(value)) {
resetObj(objRef[key]);
} else {
var myvarType = typeOf value;
objRef[key] = defaults[myvarType];
}
}
);
}
I copied this nesting function from other answer, just to add my two cents.

A good way to deal with this would be to use a class instead of an object literal, like:
class current {
constructor() {
this.key1 = undefined;
this.key2 = [];
this.key3 = undefined;
}
}
And whenever you want to clear all the values you can just create a new instance of this class, like:
$scope.display.current = new current();

function isObject (value) {
return value && typeof value === 'object' && value.constructor === Object;
}
const resetObj = (obj, resetVal) => {
if(!isObject(obj)) return;
for(let i in obj){
if(!obj.hasOwnProperty(i)) continue;
if(!isObject(obj[i])){
obj[i] = resetVal;
}else{
resetObj(obj[i], resetVal);
}
}
};

+++++++++++++++++++++++++Typescript solution+++++++++++++++++++++++++++
private deviceSettingsToReset: RemoteDeviceSetting;
// depp copy of response into deviceSettingsToReset variable which need to use in reset functionality in UI.
this.deviceSettingsToReset = JSON.parse(JSON.stringify(response));
// assign value from original copy.
this.selectedAlgorithm = JSON.parse(JSON.stringify(this.deviceSettingsToReset));

Related

How to access a nested property of an object using a string?

I have the following string:
const str = "prop1.prop2.prop3"
I want to use this string to access the property prop3 of the following object:
const obj = {
prop1: {
prop2:{
prop3:{
// ---- destination point
}
}
}
}
But I'm not able to figure out how to do it?
there must be something that keeps adding the obj[currentProp] so on and so on. and.. isn't there a quicker method? I'm afraid I'm wasting my time on something that can be achieved more easily
This would be my approach:
const access = (path, object) => {
return path.split('.').reduce((o, i) => o[i], object)
}
const obj = {
prop1: {
prop2: {
prop3: {
value: 'foo'
}
}
}
}
const str = 'prop1.prop2.prop3'
console.log(access(str, obj)) // {"value": "foo"}
You can combine split with forEach as follows:
const str = "prop1.prop2.prop3"
const obj = {
prop1: {
prop2:{
prop3:{
a: "b",
c: "d"
}
}
}
}
var srch = obj;
str.split(".").forEach(item => (srch = srch[item]));
console.log(srch); // { a: "b", c: "d"}
console.log(obj);
split converts str's value into an array, which is then looped and on each iteration, srch gets one level deeper.
different ways to access a nested property of an object
using a function accessDeepProp with two arguments the object and path of the nested property!
Recursive way:
function accessDeepProp(obj, path) {
if (!path) return obj;
const properties = path.split(".");
return accessDeepProp(obj[properties.shift()], properties.join("."));
}
For-loop way:
function accessDeepProp(obj, path) {
const properties = path.split(".");
for (let i = 0; i < properties.length; i++) {
if (!obj) return null;
obj = obj[properties[i]];
}
return obj;
}
Eval way: never_use_eval!
function accessDeepProp(objName, path) {
try {
return eval(`${objName}.${path}`);
} catch (e) {
return null;
}
}
you could also use lodash get method
This is the shortest solution, and it supports arrays and ['bracket notation']. Just don't run it against malicious user input.
Update: a better(?) version without eval.
const obj = {
prop1: {
prop2: {
prop3: {
value: 'foo'
}
}
}
}
const str = 'prop1.prop2.prop3'
//console.log(eval("obj." + str))
// a code without eval
var value = (Function("return obj." + str))();
console.log(value);

Get the key of a JS Object from the value

I am trying to get the key of a JS Object in Typescript from an input value, the problem is that the values are inside an Array.
This is what I have seen in the case that the value is not in an array:
const exampleObject = {
key1: 'Geeks',
key2: 'Javascript'
};
function getKeyByValue(object, value) {
for (var prop in object) {
if (object.hasOwnProperty(prop)) {
if (object[prop] === value)
return prop;
}
}
}
console.log(getKeyByValue(exampleObject,'Geeks')) // key1
This is an example of my object that I want to get the key from:
const exampleObject = {
key1: ['Geeks','test1','test2'],
key2: ['Javascript','test3','test4']
};
function getKeyByValue(object, value) {
for (var prop in object) {
if (object.hasOwnProperty(prop)) {
if (object[prop] === value)
return prop;
}
}
}
console.log(getKeyByValue(exampleObject,'Geeks')) // undefined
I need to get the key without using Array.prototype.includes(), because typing the resulting variable as String gives me an error that it may be undefined.
My problem: I don't know how to go through the array inside the function to find the value and get the key
Update:
What I want is to avoid the possibility of returning an undefined, since the input value will always be inside the object, how can I achieve this?
#segmet
You can use my code
const exampleObject = {
key1: ['Geeks', 'test1', 'test2'],
key2: ['Javascript', 'test3', 'test4']
};
function getKeyByValue(object, value) {
var output = "";
for (var prop in object) {
// finding and removing element from array
object[prop].find(i => {
if (i === value) {
output = prop;
return prop;
}
}
)
}
return output
}
console.log(getKeyByValue(exampleObject, 'Geeks'))
You can achieve this with a single line of code by using 3 JavaScript methods - Object.keys(), Array.find() & Array.indexOf() :
const exampleObject = {
key1: ['Geeks','test1','test2'],
key2: ['Javascript','test3','test4']
};
function getKeyByValue(object, value) {
const res = Object.keys(exampleObject).find(key => exampleObject[key].indexOf(value) !== -1);
return res || ''
}
console.log(getKeyByValue(exampleObject,'Geeks'))
function getKeyByValue(object, value) {
const key = Object.entries(object).filter(([key, val]) => val.includes(value));
return Object.fromEntries(key);
}
Try this function instead
You will get the object matching your keys
You can do something like this and then check for null
const getKeyFromValue = (obj:Object, value:string | string[]) => {
for (let key in obj) {
if (typeof value === 'string') {
if (obj[ key ].includes(value)) {
return key;
}
}
else if (Array.isArray(value)) {
if (obj[ key ].every(val => value.includes(val))) {
return key;
}
}
}
return null;
}
One more try:
const exampleObject = {
key1: ['Geeks','test1','test2'],
key2: ['Javascript','test3','test4']
};
function getKeyByValue(obj, data) {
for (const [key, value] of Object.entries(obj)) {
return (~value.indexOf(data)) ? key : false
}
}
console.log(getKeyByValue(exampleObject,'Geeks'))

How to convert a nested object to a string indexed object

I am trying to convert a nested object to a string indexed object, so I can use Vue to display all properties in an object. For example:
var obj = {
key1: 'value1',
key2: {
key3: {
key5: 'value5',
key6: 'value6'
},
key4: 'value4'
}
};
Should be convert to this:
var obj = {
'key1': 'value1',
'key2.key3.key5': 'value5',
'key2.key3.key6': 'value6',
'key2.key4': 'value4'
}
I tried to walk recursively through the object, but I didn't figure out how to get the correct index value and return both the index and the object at the same time.
What I've tried so far:
// let result = objConversion(obj)
objConversion (obj) {
let resultObject = {}
// Walk through the first level
for (let index in obj) {
if (obj.hasOwnProperty(index)) {
let extractedObj = getObjNameRecursive(obj[ index ], index)
resultObject = { ...resultObject, ...extractedObj }
}
}
return resultObject
}
getObjNameRecursive (obj, name) {
let resultObject = {}
if (typeof obj === 'object') {
// Dive into an object
for (let index in obj) {
if (obj.hasOwnProperty(index)) {
if (typeof obj[ 'index' ] === 'object') {
resultObject = { ...resultObject, ...getObjNameRecursive(obj[ 'index' ], name + '.' + index) }
} else {
resultObject = {...resultObject, [name + '.' + index]: obj[index]}
}
}
}
} else {
// Simple assign if not an object
resultObject[ name ] = obj
}
return resultObject
}
But this gives the result like:
obj = {
'key1': 'value1',
'key2.key3.key5': [object Object],
'key2.key3.key6': [object Object],
'key2.key4': 'value4'
}
The answer in Convert string to an attribute for a nested object in javascript is very close to what I want. But what I want is to get the string of attributes of a nested object.
Is there any better way to do this?
Thanks.
Try this
function convert(obj, key, result) {
if(typeof obj !== 'object') {
result[key] = obj;
return result;
}
const keys = Object.keys(obj);
for(let i = 0; i < keys.length; i++){
const newKey = key ? (key + '.' + keys[i]) : keys[i];
convert(obj[keys[i]], newKey, result);
}
return result;
}
call it
convert(obj, '', {});

Update fields in nested objects in Typescript / Javascript

In Firestore you can update fields in nested objects by a dot notation (https://firebase.google.com/docs/firestore/manage-data/add-data?authuser=0#update_fields_in_nested_objects). I wonder how to make that work in Typescript / Javascript.
For example the following object:
const user = {
id: 1
details: {
name: 'Max',
street: 'Examplestreet 38',
email: {
address: 'max#example.com',
verified: true
}
},
token: {
custom: 'safghhattgaggsa',
public: 'fsavvsadgga'
}
}
How can I update this object with the following changes:
details.email.verified = false;
token.custom = 'kka';
I already found that Lodash has a set function:
_.set(user, 'details.email.verified', false);
Disadvantage: I have to do this for every change. Is their already a method to update the object with an object (like firestore did)?
const newUser = ANYFUNCTION(user, {
'details.email.verified': false,
'token.custom' = 'kka'
});
// OUTPUT for newUser would be
{
id: 1
details: {
name: 'Max',
street: 'Examplestreet 38',
email: {
address: 'max#example.com',
verified: false
}
},
token: {
custom: 'kka',
public: 'fsavvsadgga'
}
}
Does anyone know an good solution for this? I already found more solutions if I only want to change one field (Dynamically set property of nested object), but no solution for more than one field with one method
I think you are stuck with using a function but you could write it yourself. No need for a lib:
function set(obj, path, value) {
let parts = path.split(".");
let last = parts.pop();
let lastObj = parts.reduce((acc, cur) => acc[cur], obj);
lastObj[last] = value;
}
set(user, 'details.email.verified', false);
if what you want to do is merge 2 objects then it is a bit trickier:
function forEach(target, fn) {
const keys = Object.keys(target);
let i = -1;
while (++i < keys.length) {
fn(target[keys[i]], keys[i]);
}
}
function setValues(obj, src) {
forEach(src, (value, key) => {
if (value !== null && typeof (value) === "object") {
setValues(obj[key], value);
} else {
obj[key] = value;
}
});
}
let obj1 = {foo: {bar: 1, boo: {zot: null}}};
let obj2 = {foo: {baz: 3, boo: {zot: 5}}};
setValues(obj1, obj2);
console.log(JSON.stringify(obj1));
One solution in combination with lodash _.set method could be:
function setObject(obj, paths) {
for (const p of Object.keys(paths)) {
obj = _.set(obj, p, paths[p]);
}
return obj;
}

Lowercase JavaScript object values

I have an array of JavaScript objects:
var obj = [{key1: Value1, key2: VALUE2},{key1: Value1, key2: VALUE2}];
I want the value of the key2 to be in lowercase, like this:
var obj = [{key1: Value1, key2: value2},{key1: Value1, key2: value2}];
How can I change the value from lowercase to uppercase?
If I understand your question correctly, you want to change the value of each object's key2 property, to be a lowercase string (I'm assuming they're strings).
You can do this with a simple map.
obj = obj.map(function(a) {
a.key2 = a.key2.toLowerCase();
return a;
});
There are some differences in all the answers given here, surrounding object references. In my answer above, the array itself will be a new reference, but the objects inside will remain as the same reference. To clarify this by way of example
var mapped = obj.map(function(a) {
a.key2 = a.key2.toLowerCase();
return a;
});
console.log(obj === mapped) // false
console.log(obj[0] === mapped[0]) // true
If you're using a for loop or a forEach array function, then the array reference will remain the same.
See this fiddle for reference.
You can use built-in array functions like forEach or map
// in-place
obj.forEach(function (item) {
item.key2 = item.key2.toLowerCase()
})
or
var mapped = obj.map(function (item) {
return Object.assign(item, { key2: item.key2.toLowerCase() });
})
You just have to loop through the array and lowercase the value of key2 for every object.
var objects = [{key1: "Value1", key2: "VALUE2"},{key1: "Value1", key2: "VALUE2"}];
for(var i = 0;i < objects.length;++i) {
objects[i].key2 = objects[i].key2.toLowerCase();
}
You could iterate the array and the keys, you want to change, and assign the lowercase value if you have a string.
var array = [{ key1: 'Value1', key2: 'value2' }, { key1: 'Value1', key2: 'value2' }];
array.forEach(function (a) {
['key2'].forEach(function (k) {
if (typeof a[k] === 'string') {
a[k] = a[k].toLowerCase();
}
});
});
console.log(array);
A version with a fixed key.
var array = [{ key1: 'Value1', key2: 'value2' }, { key1: 'Value1', key2: 'value2' }];
array.forEach(function (a) {
if (typeof a.key2 === 'string') {
a.key2 = a.key2.toLowerCase();
}
});
console.log(array);
Concept:
Create a function to lowercase an item based on the given key.
Then, iterate items and parse each item on those function.
Create a function to lowercase the item based on the given key:
function lowerObj(obj, key) { obj['' + key] = obj['' + key].toLowerCase(); return obj; }
Iterate items and parse each item on those function
var newObj = obj.map((item) => {return lowerObj(obj, 'your_key')});
So, you will get newObj with lower case for the item with the given key.
Example
function lowerObj(obj, key) {
obj['' + key] = obj['' + key].toLowerCase();
return obj;
}
var obj = [{key1: 'Value01', key2: 'Value02'}, {key1: 'Value11', key2: 'Value12'}];
var newObj = obj.map((item) => {return lowerObj(item, 'key2')});
console.log(JSON.stringify(newObj, null, 3));
caseInsensitivity = function(obj) {
Object.keys(obj).forEach(k => {
if(typeof obj[k] == 'string') {
obj[k] = obj[k].toLowerCase();
}
else if(typeof obj[k] == 'object') {
caseInsensitivity(obj[k]);
}
else {
}
});
return obj;
}
To convert all values even if the values are nested objects or arrays.
Assuming you had a JSON object like.
"params": {
"name": "LOWERNAME"
"phone": "1234567899"
}
Call your object like:
let user = {
name: params.name.toLowerCase(),
phone: params.phone
}
You could modify it to suit your situation!

Categories

Resources