I want to create an object dynamically in typescript / javascript. I have an array reqParam in an object env that might look like this: env = {reqParams : ['fromTime', 'toTime']} and it is passed to my initialising function to build an obect dynamically
const myObject = _initObject(env.reqParams);
I've started the function, but I can't figure out how to get the key and values into the new object properly.
private _initObject(raqParams: any) {
let requestTemplate = {
bodyjson : "$util.escapeJavaScript($input.json('$'))",
"cognitoUserId": "$context.authorizer.claims.sub",
"cognitoUserEmail": "$context.authorizer.claims.email"
};
reqParams.forEach(param => {
// build new item
let templateEntry = "$input.params('`param`')";
// Put new item into object
requestTemplate[`param`] = templateEntry;
});
}
Hopefully, you can see what I'm trying to achieve. For example, here's the desired outcome for 2 reqParams : fromTime and toTime:
{
bodyjson : "$util.escapeJavaScript($input.json('$'))",
"fromTime": "$input.params('fromTime')",
"toTime": "$input.params('toTime')",
"cognitoUserId": "$context.authorizer.claims.sub",
"cognitoUserEmail": "$context.authorizer.claims.email"
}
1 typo and 2 fixes and it works, like so:
const _initObject = (reqParams) => {
let requestTemplate = {
bodyjson : "$util.escapeJavaScript($input.json('$'))",
"cognitoUserId": "$context.authorizer.claims.sub",
"cognitoUserEmail": "$context.authorizer.claims.email"
};
reqParams.forEach(param => {
// build new item
let templateEntry = `$input.params('${param}')`;
// Put new item into object
requestTemplate[param] = templateEntry;
});
return requestTemplate;
}
console.log(_initObject(['fromTime', 'toTime']));
reqParams.forEach(param => {
// build new item
let templateEntry = `$input.params('${param}')`;
// Put new item into object
requestTemplate[param] = templateEntry;
});
js use ${} for the string interpolation
key = 'dynamic'
object[key] = value
will give you a object of {'dynamic':value}
Related
Is there way to change the index dynamically? or rebuild this object to where the 1 will be the Id of what ever object get passed into the function? Hope this makes sense.
export const createTree = (parentObj) => {
//keep in memory reference for later
const flatlist = { 1: parentObj }; <---- change the 1 based on parent.Id
...
}
My attempt thinking it would be easy as:
const flatlist = { parentObj.Id: parentObj };
Use computed property names to create a key from an expression:
const createTree = (parentObj) => {
const flatlist = { [parentObj.id]: parentObj };
return flatlist;
}
console.log(createTree({ id: 1 }));
I'm working on a VueJS component that, among other things, can export data to .xlsx. For this, I'm using the json2xls library - so I need to pass to the json2xls() function an array of objects with identical keys (said keys will be column names)
This data I have to export is in an array of pretty deeply nested objects, though, so I need a function that will process that data to a form that will work with json2xls.
This is the method I'm using for that:
exportReport () {
const dataMap = []
this.reportPreview.forEach(elm => {
const auxObj = {}
auxObj.name = `${elm.client.first_name} ${elm.client.surname_1} ${elm.client.surname_2}`
elm.legal_files.forEach((e) => {
auxObj.legalfile = e.code
auxObj.actions = e.actions.count
dataMap.push(auxObj)
})
})
exportToXls(dataMap, `action-report-by-client-${this.options.start_date}-${this.options.end_date}.xlsx`)
}
If I do this, however, it appears that in cycles of elm.legal_files.forEach() the properties auxObj.legalfile and auxObj.actions are not overwritten, pushing several objects with identical values to dataMap
Why is this happening? What am I doing wrong? I'm hacking my way around this copying auxObj after "overwriting" the legalfile and actions properties and pushing the copy. This hack works, but I wonder what causes the first behavior and if there's a cleaner way around it.
exportReport () {
const dataMap = []
this.reportPreview.forEach(elm => {
const auxObj = {}
auxObj.name = `${elm.client.first_name} ${elm.client.surname_1} ${elm.client.surname_2}`
elm.legal_files.forEach((e) => {
auxObj.legalfile = e.code
auxObj.actions = e.actions.count
/*
If I just push auxObj to dataMap, the object is pushed with the same properties every time.
Copying auxObj and pushing the copy is a hack around this problem, but there may be a cleaner solution.
*/
const objCopy = { ...auxObj }
dataMap.push(objCopy)
})
})
exportToXls(dataMap, `action-report-by-client-${this.options.start_date}-${this.options.end_date}.xlsx`)
}
You pushed the same object every time.
exportReport() {
const dataMap = []
this.reportPreview.forEach(elm => {
const name = `${elm.client.first_name} ${elm.client.surname_1} ${elm.client.surname_2}`
elm.legal_files.forEach((e) => {
const auxObj = {} // Create a new object here
auxObj.name = name
auxObj.legalfile = e.code
auxObj.actions = e.actions.count
dataMap.push(auxObj) // Push it into the array
})
})
exportToXls(dataMap, `action-report-by-client-${this.options.start_date}-${this.options.end_date}.xlsx`)
}
hope you are doing well. I have faced an issue. I'm creating a dynamic array but when I console that variable and check typeOf of this variable it showing an object instead of an array. Also when I access a specific element of that variable it's showing undefined. Let me know how can I resolve this issue. you can check I have declared a global variable name of test and push data in it. it should return an array because I'm pushing it in the array. But showing object.
$(document).ready(async function(){
await load_pre_data(true);
});
let pre_data= [];
let count = 1;
var test = [];
let ws = new WebSocket('wss://ws.binaryws.com/websockets/v3?app_id=1089');
async function load_pre_data() {
ws.onopen = function (evt) {
ws.send(JSON.stringify({
ticks_history: 'frxAUDJPY',
adjust_start_time: 1,
count: 5,
end: "latest",
start: 1,
style: "ticks"
}));
};
ws.onmessage = function (msg) {
let response = JSON.parse(msg.data);
let loop;
for (loop = 0; loop <= response.history.prices.length; loop++) {
test.push(1);
}
}
console.log(test);
console.log(typeof (test));
}
In Javascript every array is the type of an object and for your typechecking you can use "Array.isArray(test)".
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
You can read about isArray() method here
I'm trying to write a custom push function and only override it for a single instance. I'm trying to wire it up so every time I push to this array I can trigger my extra code. I don't want to override it for all Arrays or create a custom class if I don't have to.
First I had this:
let user_progress = {completed: [], inprogress: [] }
user_progress.completed.push = (item) => {
Array.prototype.push.call(user_progress.completed, item)
//do extra stuff
common.store_data(user_progress, RESOURCE_COLLECTION)
return undefined;
}
Then I tried this:
let Progress = function(){
this.completed = new Array()
this.inprogress = new Array()
}
let user_progress = new Progress()
user_progress.completed.push = (item) => {
Array.prototype.push.call(user_progress.completed, item)
common.store_data(user_progress, RESOURCE_COLLECTION)
return undefined;
}
user_progress.completed.push(item) works the first time you call it then it gets overwritten and becomes the standard Array.push. I assume it has something today with the Array.Prototype.push.call() and passing in user_progress.completed. What am i doing wrong? Both don't work and have the same issue. What is going on in the background here and is there an easy fix?
I am using a filter to only display data in a mat-table according to the filter.
In my case I have a mat-table where I inject an array with objects in it.
The function when I am filtering my data array:
import {Component, ViewChild} from '#angular/core';
import {MatTable} from '#angular/material';
#ViewChild('TABLE') table: MatTable<any>;
dataSource: CandidateDataSource | null;
filterTableFunction(form) {
let result = this.dataSource.data.filter(obj => {
if (form.userValidation === true) {
return obj.candidateState === 'userValidation';
}
});
this.dataSource.filteredData = [...this.result];
this.table.renderRows();
console.log('I am new datasource', this.dataSource.filteredData);
console.log('I am result', result);
}
From my console, I can see that the new filtered array is correct, however my table does not update with the new array.
I have also tried making "result" a global variable, with no luck.
EDIT:
First answer did unfortunately not solve my problem.
New code:
// public
public result = [];
filterTableFunction(form) {
console.log('#1', this.dataSource.data); //logs an array of objects
this.result = this.dataSource.data.filter(obj => {
if (form.userValidation === true) {
return obj.candidateState === 'userValidation';
}
});
console.log('#2' , this.result); // New array containing the objects with candidateState === 'userValidation'
this.dataSource.data = [...this.result];
this.table.renderRows();
console.log('#3', this.dataSource.data) // Shows replaced array from above line with the correct result
}
result variable is overwritten with old values.
Spread operator may not be required since this.dataSource.data is already an array.
Please try the following
filterTableFunction(form) {
const result = this.dataSource.data.filter(
obj => {
if (form.userValidation === true) {
return obj.candidateState === 'userValidation';
}
}
);
this.table.renderRows();
}
If you need to construct an array of values of the candidateState key from the object, you could use map().
// resultValues = ['userValidation', 'userValidation', 'userValidation', ...]
const resultValues = result.map(r => r.candidateState);
Working example: Stackblitz
With help from MichealID's answer, I got the following solution:
Filter function in component.ts
public result = [];
async submitFilter(form) {
this.result = this.dataSource.filteredData.filter(obj => {
if (form.userValidation === true) {
return obj.candidateState === 'userValidation';
}
});
const resultValues = this.result.map(r => r.candidateState);
this.dataSource.filter = resultValues[0];
console.log(this.dataSource.filteredData);
}
In my datasource.ts:
// Private
private _filterChange = new BehaviorSubject('');
private _filteredDataChange = new BehaviorSubject('');
constructor( private _candidateService: CandidateService){
this.filteredData = this._candidateService.candidateData;
}
// Filtered data
get filteredData(): any {
return this._filteredDataChange.value;
}
set filteredData(value: any) {
this._filteredDataChange.next(value);
}
// Filter
get filter(): string {
return this._filterChange.value;
}
set filter(filter: string) {
this._filterChange.next(filter);
}
filterData(data): any {
if (!this.filter) {
return data;
}
return FuseUtils.filterArrayByString(data, this.filter);
}
So, I'm on deep water here, but I made the "hack" to get the value candidateState on my array and take that string value into my filter, which would then filter out all objects containing that value. I don't think this is a good solution, since I can only check on one thing here, and not multiple filters like "candidateState" and example "salary". I does work for now and displays me all objects with the value I wished for. Thank you MichealID for your help.