Extend observableArray with data from a second source - javascript

i create an observableArray from an Ajax Source which is working pretty well. Now I want to extend some of the array items with data from a second source.
For example:
{ id: 1, name: 'Hugo', age: 18 }
... later I want to add:
{ id: 1, city: 'New York', country: 'US' }
... which should result in:
{ id: 1, name: 'Hugo', age: 18, city: 'New York', country: 'US' }
Is this possible with the ko.mapping plugin? I already did some tests with the result that the mapped properties of the items in the array have been replaced by properties from the second source.
Solution
Well, it was actually pretty easy to solve. When adding the new data with the mapping plugin I just have to check for the key. The existing data is just extended with the additional data.
ko.mapping.fromJS(modifications, {
key: function(data) {
return ko.unwrap(data.id);
}
}, originalData);

If the properties aren't observables you can use ko.utils.extend.
var original = { id: 1, name: 'Hugo', age: 18 };
var modifications ={ id: 1, city: 'New York', country: 'US' };
var result2 = ko.utils.extend(original, modifications);
console.log(JSON.stringify(result2));
See fiddle

Related

Parse JSON-like string into object using JavaScript

I have a problem about using JSON-like string parser: sometimes users will not input a correct strict JSON string. For example:
input =
"name: John,
age: 20,
products: [
{ id : 100, name: flower },
{ id : 101, name: snack },
],
home: New York,
education: {
highSchool: {
name: Stuyvesant High School,
GPA: 3.2
},
college: {
name: Fordham University,
GPA: 2.8
}
}"
The input above is not able to parse using JSON.parse() because both key and value does not fit contained by "" (name: John instead of "name": "John")
How can we get the expected output like this:
console.log(customParser(input));
//expected
/*
name: "John",
age: 20,
products: (2) [{...}, {...}]
home: "New York"
education: (2) {highSchool: {...}, college: {...}}
*/
As an alternative to writing your own parser from scratch, you might consider interpreting the user input as YAML. For example, the Node.js command require("js-yaml").load(input) converts your example input into the following Javascript object:
{
name: 'John,',
age: '20,',
products: [ { id: 100, name: 'flower' }, { id: 101, name: 'snack' } ],
home: 'New York,',
education: {
highSchool: { name: 'Stuyvesant High School', GPA: 3.2 },
college: { name: 'Fordham University', GPA: 2.8 }
}
}
Except for the trailing commas at the end of the string-valued properties, that is what you want. Either educate your users to leave these commas out, or write a pre-processor that removes them before calling the .load function of js-yaml.

DynamoDB, BatchWriteItem for an array - AWS V3

I have an array I am using to create a put for batchwriteitem.
const people = [{
location: 'London',
name: 'Tony Wilson',
pets: [ {name: 'Cuddles', age: 4}, { name: 'Jess', age: 2}]
},
{
location: 'Manchester',
name: 'Liz Smith',
pets: [ {name: 'Fluffy', age: 4}, { name: 'Keith the cat', age: 2}]
}
]
My batchwriteitem loop is working for individual items
location: { S : item.location },
but when I try and input the pets array as an array it fails
pets: { M: item.pets },
So this all works except the pets array.
const request = pets.map(item => {
const createdDate = Date.now();
return {
PutRequest: {
Item: {
location: { S : item.location },
createdDate:{ N: createdDate },
pets: { M: item.pets }
}
}
});
Do I need to break down the pets array into types and if so how can I achieve this?
Edit
pets: { L: item.pets }, does not work
**Cannot read properties of undefined (reading '0')
and the old syntax without the types does not work on v3 with the document client for me.
Pets is an array, which is also known as a list type. You are setting it as a dictionary/map type as you've set the value to M. It should be L:
pets: { L: item.pets },
I would advise that you use the Document Client as it means you do not need to think about the type conversions, and just use native JSON objects:
pets: item.pets,

Convert array of objects to another array of objects

I need to convert array of objects to just objects to use it in table datasource:
{v_report_full: Array(25)}
v_report_full: Array(25)
0:
first_name: "Blake"
last_name: "Thorphan"
middle_name: "Agder"
monh: "2021-02-01 00:00:00"
n_vh: "Delay 00:04:52"
n_vh_s_obeda: "ok"
n_vyh: "ok"
n_vyh_s_obeda: "ok"
name: "oitib"
rtime: null
vh_s_obeda_ts: null
vhod_ts: "2021-02-01 08:59:52"
vyh_s_obeda_ts: null
vyhod_ts: null
__typename: "Ereport"
__proto__: Object
1:.. the same next index
2:.. the same next index
Table datasource requires next order:
const dataSource = [
{
key: '1',
name: 'Mike',
age: 32,
address: '10 Downing Street',
},
{
key: '2',
name: 'John',
age: 42,
address: '10 Downing Street',
},
];
I've tried to use Object.keys, but have not enough expirience to do that. If here is a simple solution, if not I have to write a loop for each row with function to concat, etc?
Upd. These one was I worked with:
let dataSource = (data) ? data.v_report_full.map((value, index, array) => {
return {
id: value.id,
key: value.id,
first_name:(value, 'first_name'),
.....
}
After hatfield advise, I checked once more and it's working! A liitle changes and above code then working now D: What a noob I am.

JavaScript: Comparing two objects

I want to compare two objects to make a new object.
original = [
{id: "A1", name: "Nick", age: 20, country: 'JP', code: 'PHP'}
]
edited = [
{name: "Mike", age: 30, country: 'US'},
{id: "A1", name: "Nick", age: 25, country: 'US', code: 'PHP'}
]
Compare two objects ('original' and 'edited')
If 'id' is set, compare the same ids' data, and take the data from 'edited', and get ONLY the 'id' and the data that is edited.
If 'id' is not set keep the whole data
The final object I want is like below;
final = [
{name: "Mike", age: 30, country: 'US'},
{id: "A1", age: 25, country: 'US'}
]
I've been trying this using filter, but I can't get desired result...
Try with Array#reduce .
Updated with all key pair match
Validate the edited array id value is available in original array using Array#map and indexOf function
If not push entire object to new array
First recreate the original array to object format like {key:[value]}
Then match each key value pair match or not with forEach inside the reduce function
var original = [{id: "A1", name: "Nick", age: 20, country: 'JP'}];
var edited = [{name: "Mike", age: 30, country: 'US'},{id: "A1", name: "Nick", age: 25, country: 'US'}];
var ids_org = Object.keys(original[0]).reduce((a,b,c)=> (a[b]=original.map(a=> a[b]),a),{});
var res = edited.reduce((a, b) => {
if (b.id) {
Object.keys(b).forEach(i=>{
if(ids_org[i].indexOf(b[i]) > -1 && i != 'id')
delete b[i];
})
a.push(b);
} else {
a.push(b);
}
return a;
}, []);
console.log(res)
use de structuring to extract out id from the object.
use lodash isEqual method to compare and later add back the id to the object.

Native filter in JavaScript with objects?

To give background of the prompt (this isn't homework, but some questions that someone forwarded me to help with understanding how to use HOF and implementing them correctly so all explanations as well as different approaches to the problem are welcomed):
a) Implement a findPerson method that takes an Array of people and a name String as the target. Each person Object is structred:
{name: 'Erika', gender: 'Female'}
usage example:
findPerson(people, 'Erika') // -> {name: 'Erika', gender: 'Female'}
Constraint: Use filter
My array of objects is as follows:
var people = [
{
name: 'Max',
gender: 'Trans'
},
{
name: 'Sue',
gender: 'Female'
},
{
name: 'Jake',
gender: 'Male'
},
{
name: 'John',
gender: 'Male'
},
{
name: 'Erika',
gender: 'Female'
}
];
The code that I have constructed thusfar is this:
const findPerson = (people, name) => {
people.filter(function(person) {
if(person.name === name){}
return person;
});
};
The problem is that I am running into this error as follows:
should return an object ‣TypeError: Cannot read property 'should' of undefined
should return the proper object ‣TypeError: Cannot read property 'should' of undefined
If anyone could be of assistance of pointing me in the right direction as to how to go about my logic of solving this and where did I go wrong in my code?
filter function should return true or false:
var people = [
{name: 'Max', gender: 'Trans'},
{name: 'Sue', gender: 'Female'},
{name: 'Jake', gender: 'Male'},
{name: 'John', gender: 'Male'},
{name: 'Erika', gender: 'Female'}
];
const findPerson = (people, find) => people.filter(({name}) => name === find)[0];
console.log(findPerson(people, 'Erika'))
const people = [{
name: 'Max',
gender: 'Trans'
},
{
name: 'Sue',
gender: 'Female'
},
{
name: 'Jake',
gender: 'Male'
},
{
name: 'John',
gender: 'Male'
},
{
name: 'Erika',
gender: 'Female'
}
];
const findPerson = (persons, name) => {
return persons.filter((person) => person.name === name);
};
console.log(findPerson(people, 'Erika')[0]);
The issue with your code is that you were not returning the value of calling filter.
filter after it has run, returns an array. It's that returned array that will contain the value that was filtered out.
I did this: findPerson(people, 'Erika')[0] to select the first item from the array since the return value of filter is an array.

Categories

Resources