I have a JSON object with two arrays of an object x.
I'm using angularJS and I want to add/edit/delete objects in the JSON (just like the Angular TODO app example on angular.org).
Is there a way to create a new empty (with the structure of x but no values) JSON object of x, and simply push that to the above JSON object array?
How do I go about creating an empty value JSON object of x?
My Sample object x is (I nullified all the values) pasted below. So my JSON is just an array of these objects. In Angular, I want the user to fill out a form and hold the data in an empty object of this type and push it to the array. That's my goal.
Sample JSON
[{
"id": null,
"title": "",
"date": {},
"billPayerId": null,
"notes": "Sample Notes",
"billFinances": {
"billPayerId": null,
"billItemEntry": [
{
"itemDescriptionId": 1,
"itemDescription": "",
"userIdAndLiableCost": [
{
"userId": null,
"liableCost": null
},
{
"userId": null,
"liableCost": null
}
]
},
{
"itemDescriptionId": null,
"itemDescription": "",
"userIdAndLiableCost": [
{
"userId": null,
"liableCost": null
},
{
"userId": null,
"liableCost": null
}
]
}
],
"billTotal": null
},
"groupId": null
}];
You can use an object literal to store whatever you want. It is just a bag of properties (i.e. name) and values. e.g. var order = {};
Then an array literal could be used to hold the orders. e.g var orders = []; orders.push(order); But it would be just as easy to use another object literal with the id as a property.
But it seems like you want some sort of validation. Perhaps something to manage the order data and handle the validation, etc. Like so:
orderManager.dataStore = {
_data: {},
//_redundantData = []; //could easily store in an array if id isn't unique
get: function (id) {
return this._data[id];
},
getAll: function () {
return this._data;
},
set: function (id, order) {
validateOrder(order);
this._data[id] = order;
},
clear: function (id) {
this._data[id] = undefined;
},
add: function (order) {
validateOrder(order);
this._data[order.id] = order;
},
assertNotNull: function (data, key) {
if(data[key] == undefined) {
throw new Error("Key Missing: " + key + " for " + data.name);
}
},
validateOrder: function(order) {
assertNotNull(order,"id");
assertNotNull(order,"title");
//etc
},
containsOrder: function (id) {
for(var i=0;i<array.length;i++) {
if(array[i].id === id) {
return true;
}
}
return false;
}
};
If I'm reading all of this right, I think you may be misunderstanding how Angular works. You don't have to create an empty object for Angular to use within a form. As long as your form's inputs use dot notation, it will generate the object for you as the user fills in the inputs with data.
E.g.
<form>
<input type="text" ng-model="myForm.name">
<input type="text" ng-model="myForm.email">
<input type="text" ng-model="myForm.nickname">
</form>
Since we used the dot notation in the ng-model attribute, it creates the object for us as the user fills out the form. The generated object would look like this after the inputs are completed:
$scope.myForm = {
name: 'Justin',
email: 'justin#email.com',
nickname: 'Cerebrl'
};
Now, normally once the user clicks save, you'd send the data to the server for persistence and you could then just empty the object (e.g. $scope.myForm = {};) to reset the form. But, for some reason, you want to build an array first, then send the whole thing to the server when fully complete (at least that's how I'm understanding it).
To do this, you have to get around the fact that Objects and Arrays in JavaScript are reference types, so you can't push the object full of data to an array, and then empty the object to reset the form as that would then empty the object within the array as well, blowing your data store.
I would personally address this problem with Angular's object copy method (e.g. angular.copy(source);) seen here: http://docs.angularjs.org/api/angular.copy This allows you to make a non-referenced copy of an object and use it without mutating the original object. So, within the "save function", you would have this:
var myNewObj = angular.copy($scope.myForm);
myDataArray.push(myNewObj);
$scope.myForm = {};
That way, you've saved the completed form data, pushed it to the array and cleared the form's input data. Does this answer your question?
Related
I am still fairly new to JavaScript and I need help with an issue I am having.
I have a Java function that returns an array of json objects as such:
{
"payload": {
"phone": "1234567890",
"email": "test#test.com",
"contact": {
"personal": "test test",
"professional": "professionaltest test"
}
}
}
Now I have various scenarios in my API test where I am sending a POST request but purposefully missing some of the key/value pairs in the json. Such as:
Send the request by skipping contact.
Send the request by skipping phone.
etc.
I have researched and it seems that using .splice can be used to remove an object. However, from what I understand, the removal criteria is primarily driven by indexes (indices?). I'd rather not use remove by index in case something changes the output of the function in the future. Is there a way to remove by key name? Any alternative methods would be greatly appreciated too.
This is my favorite way to remove an value from an object.
For example, you want to remove phone from the payload object.
var { payload } = // your object
var { phone, ...newValue } = payload
console.log(newValue)
newValue is an copy of payload object without the phone key value.
function removeByKeys(obj, keys) {
return Object.keys(obj).reduce((newObj, key) => {
if (keys.includes(key)) {
return newObj;
}
return { ...newObj, [key]: obj[key] };
}, {});
}
const person = { name: 'bob', age: 36 };
removeByKeys(person, ['age']); // { name: 'bob' }
The has the same API as lodash omit. https://lodash.com/docs/4.17.15#omit. You can use that if you have more complicated use-cases, but the above is simple enough.
This question already has answers here:
Find object by id in an array of JavaScript objects
(36 answers)
Closed 2 years ago.
I have a file with 1000s of json rows like below. Im having difficulties locating a specific key in the array.
example json:
{"connection":"98374"
,"db":"8",
,"timestamp":"159905411631"
,"event":"DataCatch"
,"data":[{"key":"ruleid","value":"111"}
,{"key":"responseid","value":"155-response-4"}
,{"key":"responsetype","value":"Capture"}
,{"key":"reason","value":"ClientVisit"}
,{"key":"subreason","value":""}
,{"key":"score","value":"0.00"}
,{"key":"comment","value":""}]
}
I need to be able to find the "reason" key in the "data" array and replace the "value" with "test". The "data" array doesn't always appear on every json row, only when the "event" "dataCatch" is present.
I can parse it into a variable but I can only call the "data" array as a whole. Any ideas how to target specific values in an array?
Having a little trouble with this in Typescript.
There are any number of ways to go about this, but here's one.
First, parse your JSON into an array of objects.
Each element of the array will then look something like this:
{
connection: '98374',
db: '8',
timestamp: '159905411631'
event: 'DataCatch',
data: [
{ key: 'ruleid', value: '111' },
{ key: 'responseid', value: '155-response-4' },
{ key: 'responsetype', value: 'Capture' },
{ key: 'reason', value: 'ClientVisit' },
{ key: 'subreason', value: '' },
{ key: 'score', value: '0.00' },
{ key: 'comment', value: '' },
],
}
Let's call our array of objects allData, so we can refer to it later.
Now we can begin our "surgery".
We'll work from the inside-out, first looking at what needs to be done to a specific entry in an element's data array.
Here's a function that will do just what we need:
function updateReason(entry) {
if (entry.key === 'reason') {
return { ...entry, value: 'test' };
} else {
return entry;
}
}
This function checks if the provided entry has a key with a value of 'reason', and -- if so -- returns a new entry that is identical to the provided one except its value is 'test'.
How can we use this to update an entire data array (in an entry that has data, that is)?
We simply delegate the work to our dear friend map:
function updateData(data) {
// or simply `data.map(updateEntry);`
return data.map(entry => updateEntry(entry));
}
We're slowly working our way "outwards".
What about updating an entire entry in our big allData array (which may or may not contain data)?
// I've called such an entry a "collection", because I already used the name
// "entry" above :(
// A "collection" is just an entry in the big `allData` array.
function updateCollection(collection) {
if (collection.event === 'DataCatch') {
return {
...collection, // Leave everything else the way it is
data: updateData(collection.data), // But update the `data` array
};
} else {
return collection;
}
}
So close.
The last thing we need to do is apply this transformation to every element of our parsed allData array:
// or `allData.map(updateCollection);`
const updatedData = allData.map(collection => updateCollection(collection));
Also:
Q: Wouldn't it be cheaper to mutate the entry?
A: It would be cheaper, but not that much cheaper, due to a large amount of "structural sharing" that occurs here. I would recommend this approach unless you either need to mutate your input for some reason, or performance requirements demand it.
You need to map over the data key in your data variable like this.
data.data = data.data.map((item) => {
if (item.key === "reason") {
item.value = "test";
}
return item;
});
the data key is an array of values, so you need to loop through it and compare the value of the key property to the value you are looking for, if it matches then you can update the value property
https://codesandbox.io/s/angry-shirley-1gh83?file=/src/index.ts:666-782
I have a simple scenario where I am trying to update an array value that is part of an object, but the object does not seem to reflect the update.
Code:
var request =
{
description: 'my-desc',
details: []
};
request.details['shelf-info'] =
[
{
key: 'ShelfNumber',
value: '100'
}
];
console.log(JSON.stringify(request))
With the assignment of shelf-info, I would have expected the resulting output to be similar to:
Desired Output:
{ "description": "my-desc", "details": { "shelf-info": [ "key": "ShelfNumber", "value": "100" ] } }
but the update doesn't seem to have taken effect:
Actual Output:
{"description":"my-desc","details":[]}
I have found that I can add simple objects (strings) to an array using append, but shelf-info may or may not already be in the request.details section by the time this code gets executed...how would I handle both cases?
You want a plain object ({}) for details, not an array ([]).
When arrays are serialized to JSON, the JSON output only includes values that are stored in whole-number indices. Arrays may validly have other properties whose key names are not non-negative integers (such as the string shelf-info) but those properties are not included the JSON serialization of the array.
You're using an array as if it's an object, which it technically is, but that won't add anything to the array, and it won't convert the array to a regular object with key/value pairs.
Easy fix:
var request = {
description: 'my-desc',
details: { }
};
Also since it's 2020 you should be using let instead of var in most cases.
Try Below. Detail property should be an object.
var request =
{
description: 'my-desc',
details: {}
};
request.details['shelf-info'] =
[
{
key: 'ShelfNumber',
value: '100'
}
];
console.log(JSON.stringify(request))
I would like to be able to iterate through and access the 'name' field values of an avro schema but have not been able to find an efficient way of doing so without getting extra values due to the particular way avro expects its schema data.
I can recursively iterate through it as though it were a js object; however, I end up with certain fields I did not want being included in my results.
For example, in the below code the only value I want to get back is 'foobar' however I also get 'Foo' which I do not want as that is the name of an array of objects rather than a single value.
{
"type": "record",
"name": "Foo",
"fields": [
{
"name": "foobar",
"type": "string"
}
]
}
The current function I am using looks like this:
iterateAvro = (target) => {
let result = [];
Object.entries(target).forEach(([key, val]) => {
if (val === null){
return null
}
if (typeof val === 'object'){
result = result.concat(this.iterateAvro(val));
} else {
if(key === 'name'){
result.push(val)
}
}
})
return result
}
I am new to avro (and coding in general) and do not know if there is an avro specific way of doing this. Any help would be appreciated.
What you are doing in your function is:
Convert a JavaScript object into an array of key/value pairs.
Iterating through the pairs and:
a. If the value is null do nothing.
b. If the value is an object, apply this logic to it using recursion.
c. If the key is name push the value to an array called result accessed through a Clojure.
Your function is grabbing any value whose key is name. That is why both foobar and Foo are returned.
Looking at Apache Avro's documentation I see that inside the fields key, there is a list with multiple field objects, each of which must have a name key.
So, assuming that you would like to get the values of all the field names you could do something like this:
// JSON object gotten directly from Apache Avro's documentation.
var avroRecord = {
"type": "record",
"name": "LongList",
"aliases": ["LinkedLongs"], // old name for this
"fields" : [
{"name": "value", "type": "long"}, // each element has a long
{"name": "next", "type": ["null", "LongList"]} // optional next element
]
}
function getFieldsNames(record) {
return avroRecord.fields.map((field) => {
return field.name;
});
}
console.log(getFieldsNames(avroRecord))
// [ 'value', 'next' ]
I hope this helps.
I'm trying to remove an object from Json Object it works..but it replace it with null..i dont know why, how can i remove the null value from the json..heres the function :
company.deleteExternalLinkFromGrid = function (row, matricule) {
// console.log('Inside of deleteModal, code = ' + code);
//$scope.sitting= {};
console.log(matricule);
//console.log(JSON.stringify(linkJsonObj));
delete linkJsonObj[matricule];
console.log(JSON.stringify(linkJsonObj));
};
heres the object:
[{"name":"xxx","link":"www.ddd.com","id":0,"$$hashKey":"uiGrid-001Z"},null,null]
You can use filter(), x will be without null's.
function test()
{
var x =[{"name":"xxx","link":"www.ddd.com","id":0,"$$hashKey":"uiGrid-001Z"},null,null].filter(isNotNull);
alert(JSON.stringify(x));
}
function isNotNull(value) {
return value != null;
}
fiddle
There are multiple ways to delete an object from an array of objects in JavaScript. You don't need AngularJS for that, you can use VanillaJS.
If you just want the nulls filtered you can use
var yourArray =[{"name":"xxx","link":"www.ddd.com","id":0,"$$hashKey":"uiGrid-001Z"},null,null];
yourArray = yourArray.filter(function(elt){
return elt != null;
});
But this loses the original reference to your object.
If you want to keep the reference, Use array.splice().
yourArray.forEach(function(){
yourArray.splice(yourArray.indexOf(null),1);
});
now you will have null less array in yourArray. This actually deletes an object from an array without changing the reference,
delete will replaced the object with undefined
You can filter the array to remove them using Array#filter()
var array = [{
"name": "xxx",
"link": "www.ddd.com",
"id": 0,
"$$hashKey": "uiGid-001Z"
}, {
"name": "xx",
"link": "www.dddcom",
"id": 1,
"$$hashey": "uiGrid-0029"
}, {
"name": "xxx",
"link": "www.ddd.com",
"id": 2
}];
delete array[1];
array = array.filter(a=>a);
console.log(JSON.stringify(array));