I have an obejct:
obj1 = {
id: 123,
name: "ABC test",
desc: "SPme test sdesctiption",
data: [{name:"data1"}],
createdBy: "Some person",
updatedBy: "Some persone22"
}
Now when we edit the details of this data from client side, we need to update only those fields from the object that has been changed.
ex:
updatedObj = {
id: 123,
name: "ABC12222222 test", // changed
desc: "SPme test sdesctiption",
data: [{name:"data1"}],
createdBy: "Some person",
updatedBy: "Some persone22"
}
In above case I only want to change the name, but this data can be dynamic and based on what user changes, we need to update only thoe fields in the obj1
I tried :
newObj = Object.assign(obj1, {updatedObj})
but this inserts all new object inside obj1. I tried using Shallow copy of objects but that did not quite work.
any ideas how this can be achieved?
Since updatedObj have all the fields instead of just the changed fields
newObj = updatedObj
Related
I have a scenario where I want to change properties of object in an array. That array is wrapped inside another object.
const defaultData = {
title: "Title",
subtitle: "Subtitle",
books: [
{
bookId: "1",
imageSrc:
"any.png",
name: "Issue",
userOwnsData: true,
panelsCollected: 0,
totalPanels: 123,
link: "https://google.com",
},
],
bgColor: "black",
};
When I spread it like this:
{...defaultData, ...defaultData.books[0], panelsCollected:123} //previously it was 0
then it adds another extra object to parent object but not update it inside first index of books array
How can I just change that panelsCollected property without disturbing whole structure as we are using typescript.
Edit:
We can change it directly accessing the property too as we know index but that comes with a side effect of manipulating original dataset also which we should avoid and only copy needs to be updated.
Thanks
When spreading an object with nested properties with the intention of updating specific properties, think of it in two steps:
Spread the original object to copy it (...)
Redefine the new property values after the spread object
In your example we are doing the following:
Duplicating defaultData and assigning an updated books property (to be defined in the next step)
Duplicating the first book (defaultData.books[0]) and assigning an updated panelsCollected property to it. Then overwriting the existing books property with this updated array item
The result is as follows:
const defaultData = {
title: "Title",
subtitle: "Subtitle",
books: [
{
bookId: "1",
imageSrc:
"any.png",
name: "Issue",
userOwnsData: true,
panelsCollected: 0,
totalPanels: 123,
link: "https://google.com",
},
],
bgColor: "black",
};
const newBook = {
...defaultData,
books: [
{
...defaultData.books[0],
panelsCollected: 123
}
]
}
console.log(newBook)
/*
{
title: "Title",
subtitle: "Subtitle",
books: [
{
bookId: "1",
imageSrc:
"any.png",
name: "Issue",
userOwnsData: true,
panelsCollected: 123,
totalPanels: 123,
link: "https://google.com",
},
],
bgColor: "black",
};
*/
If for example the books property was 1000 items long, you would instead use have to find the specific book in your array using an array method (e.g. find / findIndex) and update it, e.g.
const bookToUpdateIndex = defaultData.books.findIndex(book => book.bookId === '1')
const updatedBooks = [...defaultData.books]
updatedBooks[bookToUpdateIndex] = {
...updatedBooks[bookToUpdateIndex],
panelsCollected: 123
}
const newBook = {
...defaultData,
books: updatedBooks
}
I think it is creating another parent object because you are using the spread twice. I tried to do 2 console logs. Please let me know if this is the result you are looking for.
console.log({...defaultData['books'][0]['panelsCollected'] = 10})
console.log(defaultData);
Instead of using find and the spread syntax an alternative approach (but not necessarily the most performant) might be to copy the object by stringifying it, and then reparsing that string. And then you can just update the object at the index you need.
const defaultData={title:"Title",subtitle:"Subtitle",books:[{bookId:"1",imageSrc:"any.png",name:"Issue",userOwnsData:!0,panelsCollected:0,totalPanels:123,link:"https://google.com"}],bgColor:"black"};
const copy = JSON.parse(JSON.stringify(defaultData));
copy.books[0].panelsCollected = 123;
console.log(defaultData);
console.log(copy);
I have an array as such:
arr = {
name: 1,
address: 1,
phone: 2,
email: 5,
};
I want to be able to add further information to this array, eg:
arr = {
name: 1 true,
address: 1 false,
phone: 2 true,
email: 5 true,
};
I've tried a few different things like:
arr.email[2] = true;
With no results (or errors).
Is there a way to do this? Or a better way of handling this issue?
I'm not entirely certain what you're going for here since you mention wanting an array ([]) but what you've shown in your question is an object ({}), but if I'm reading right you can accomplish this with an object where each key holds an array of values. That would look like:
const obj = {
name: [1],
address: [1],
phone: [2],
email: [5],
};
obj.email.push(true);
obj.email.push("whatever");
console.log(obj)
console.log(obj.email[1])
console.log(obj.email[2])
So obj is an object, but name, address, phone, and email are all arrays which you can extend as needed with array methods.
Original data structure doesn't allow you to add data the way you want. So you have to create the object with needed data structure at first. After this the original data should be moved to the new object and only after this you can add some new data.
newObj.name.push(origObj.name,true,"something1","something2");
newObj.address.push(origObj.address,false);
newObj.phone.push(origObj.phone,true);
newObj.email.push(origObj.email,true);
output
{
"name":[1,true,"something1","something2"],
"address":[1,false],
"phone":[2,true],
"email":[5,true]
}
original object
var origObj = {
name: 1,
address: 1,
phone: 2,
email: 5
};
new object
var newObj = {
name: [],
address: [],
phone:[],
email: []
};
You would need to assign a variable to your array and call a function...that way, each element could be classified (boolean, string, integer, etc.) For example,
const fruit = ['banana', 'apple', 'pear'];
console.log(fruit);
I have array that contains plenty of data. Format is always like that:
1:
UserName: "John Smith"
Priority: "2"
Time Occured: "02/09/2019 11:20:23"
Time Ended: "02/09/2019 11:20:23"
2:
UserName: "Tom Bill"
Priority: "4"
Time Occured: "01/08/2019 13:20:23"
Time Ended: "04/08/2019 15:20:23"
3:
UserName: "John Smith"
Priority: "2"
Time Occured: "06/08/2019 13:20:23"
Time Ended: "09/09/2019 15:20:23"
...
Of course there is more stuff, but just to give you idea of structure.
Array contains entries that might be under the same user name. As user can have multiple entries
What I want to do, is sort and modify it to the way I can use it on data table. I am not sure what approach might be the best or what is possible.
I was thinking that I need to modify array do some math in meantime. So in Data table I can present that John Smith, got 8 entries, two of them are sev 4 etc etc. Tom Bill got 4 entries etc. Basically I won't use original data as I need to modify some parts of it, for Example I am not interested in date itself, but if it was in the past or in the future, already got scripts for that, yet I need to do it for every single user.
A structure something like this seems to be sufficient for your requirement:
data = {
'John Smith' : [{ Priority : 1, .... }, { ...2nd instance }],
'John Doe' : [{...1st instance of John Doe}],
}
Basically an object that has the names for keys, and each key has an array of entries of data.
Whenever you wish to add more entries to John Smith, you get access to the array directly by using data['John Smith']
EDIT
To convert the data to this format.
data = [
{
'UserName': "John Smith",
'Priority': "2",
'Time Occured': "02/09/2019 11:20:23",
'Time Ended': "02/09/2019 11:20:23",
},
{
'UserName': "Tom Bill",
'Priority': "4",
'Time Occured': "01/08/2019 13:20:23",
'Time Ended': "04/08/2019 15:20:23",
},
{
'UserName': "John Smith",
'Priority': "2",
'Time Occured': "06/08/2019 13:20:23",
'Time Ended': "09/09/2019 15:20:23",
}
]
convertData = (data) =>{
let newData = {}
for(let i = 0; i<data.length; i++){
// console.log(data[i])
let name = data[i]['UserName']
tempData = {
'Priority' : data[i]['Priority'],
'Time Occured' : data[i]['Time Occured'],
//Add more properties here
}
if (newData[name]==null){
newData[name] = []
}
newData[name] = [...newData[name], tempData]
}
console.log(newData)
}
convertData(data)
Look at this codepen.
https://codepen.io/nabeelmehmood/pen/jONGQmX
Basically, I'm working on an HTML page where I have to print out text that's stored in another .js file. The thing is, the text is stored in an object... in an array... in a function... in a variable. So there's lots of digging to be done, just to access ONE piece of data.
Here's the data (or something similar) in the accompanying .js file:
var TestDataSet= (function() {
var reviews = [
{ Id: "abcd1234",
Title: "This Is Title Text",
Number: 5,
Body: "text",
CreateDate: new Date(2012,5,23,14,12,10,0),
Owner: {
Id: "Person1234",
Name: "James Smith",
}
},
]
How would I make the browser return "abcd1234" from the First ID? How about "Person1234" from the nested ID?
The best I've got so far is this:
var data1 = new reviews;
console.log(data1.reviews[0].Id);
But this does nothing. I get a whole lot of "not defined" errors.
Apparently you haven't posted your complete function.
However, I suggest to return the array value as in a getter function and use it if is safe for the rest of your script:
var TestDataSet= (function() {
var reviews = [
{ Id: "abcd1234",
Title: "This Is Title Text",
Number: 5, Body: "text",
CreateDate: new Date(2012,5,23,14,12,10,0),
Owner: {
Id: "Person1234",
Name: "James Smith",
}
},];
return reviews;
});
Then you can access data using:
TestDataSet[0].Id
My database returns this kind of User object:
{
name: "Name",
surname: "Surname",
scores: [<array of scores here>],
facebook_id: "fb_id_here",
access_token: "4y8y09n3vy09y0",
last_login: "some date",
register_date: "somedate"
sessions_count: 453
}
Is there any faster way of creating object containing only some key-value pairs than creating a new one with selected fields? Something like:
var NewObject = UserObject.filterFields([name, surname, sessions_count, scores]);
which should produce:
{
name: "Name",
surname: "Surname",
scores: [<array of scores here>],
sessions_count: 453
}
Thanks.
var UserObject = {
name: "Name",
surname: "Surname",
scores: [1,2,3],
facebook_id: "fb_id_here",
access_token: "4y8y09n3vy09y0",
last_login: "some date",
register_date: "somedate",
sessions_count: 453
};
function filterFields(obj, fields) {
return fields.reduce(function(ret, field) {
ret[field] = obj[field];
return ret;
}, {});
}
var NewObject = filterFields(UserObject, ['name', 'surname', 'sessions_count', 'scores']);
console.log(NewObject);
With the function, you could also do soemthing like
UserObject.filterFields = filterFields.bind(UserObject, UserObject);
then
var NewObject2 = UserObject.filterFields(['name', 'surname', 'sessions_count', 'scores']);
console.log(NewObject2);
There are many ways to do this. If you include ES6, there are even more ways. You can modify the object by deleting keys; or you can create a new object with only the fields you want. Here's one simple idea:
// Copy values for properties present on o1 from o2.
define copyFrom(o1, o2) {
Object.keys(o1).forEach(function(key) { o1[key] = o2[pkey]; });
}
Since you seem to want to be able to call this as a method on the object:
Object.defineProperty(Object.prototype, 'filterFields', {
value: function(o) { copyFrom(o, this); }
});
Now you can call this as
var NewObject = UserObject.filterFields({name: 0, surname: 0, session_count: 0, scores: 0});
The idea of using an object like {name: 0, ... to specify the keys you want may seem a bit clumsy. On the other hand, speciyfing the keys as strings is not very aesthetically pleasing either.