How to call async function from valueFormatter in ag-grid - javascript

I have an ag-grid table, and I have a column in it with value formatter:
{
headerName: "My column",
valueFormatter: getFormattedIndexValue,
...
}
From getFormattedIndexValue I try to call async function:
async function getFormattedIndexValue (params) {
if (!params.value) return;
return await getDecodedValue(table, params.colDef.field, params.value);
}
This is the code of async function, I try to call:
async function getDecodedValue(table, field, value) {
const query = `function=decode&table=${table}&field=${field}&value=${value}`;
const response = await fetch('routines.php', { method: 'post', body: query, headers: {"Content-Type": "application/x-www-form-urlencoded"}});
return response.text();
}
But in this way valueFormatter doesn't return correct value, resulting in [Object Promise]. Is there a way to call async function from valueFormatter and to get proper result

this is an old post but I hope this answer can help others because it helped me a lot.
I was using an async function to retrieve the data via Fetch to the Cell of the table. No matter what I did, I always got [Object Promise]
Then I used cellRenderer instead of ValueFormatter
I give an example here. I have some data with some people and their company ID's, I don't want the user to see company IDs in the table, I want them to see the company names instead.
These are the columns, I set the "company_id" field with cellRenderer":
var columnDefsCuotas = [
{ field: 'user_id', width: 150 },
{ field: 'name', width: 250 },
{ field: 'company_id', width: 250,
cellRenderer: GetCompanyName
}
]
Then I create a class called GetCompanyName Here I can render each cell of the table to print the name of the company instead of the ID of the company. I put the fetch in this class to retrieve the data:
class GetCompanyName {
// gets called once before the renderer is used
async init(params) {
// create the cell
this.eGui = document.createElement('div');
this.eGui.innerHTML = `<span class="my-value"></span>`;
// get references to the elements we want
this.eValue = this.eGui.querySelector('.my-value');
// set value into cell
this.cellValue = this.getValueToDisplay(params);
this.eValue.innerHTML = await getName(this.cellValue);
async function getName(company_id) {
let result = await fetch(`/fetch_companies?company_id=${company_id}`)
let response = await result.json()
console.log(response) // See if it is fetching the desired response data
return response.company_name // I return only the parameter of the object I need to see
}
}
getGui() {
return this.eGui;
}
getValueToDisplay(params) {
return params.valueFormatted ? params.valueFormatted : params.value;
}
}
I hope it helps. It worked like a charm for me!

valueFormatter doesn't suit for it, but instead, you can create cellRenderer and you would be able to handle needed logic inside.
but as I understood, you wanna have kind of reference (key to value, id(as key) on database and value(as displayed value) on view grid) - am I right?
If so, (valueFormatter and valueParser should be used) but without an async call,
you need to have your key-value pair (dictionary) on grid-init process.
Here is my example:
on ag-grid init process I'm saving dictionary for columns in config.ComboData
valueFormatter = (params) => {
return this.lookupValue(config.ComboData['columnNameHere'], params.value);
};
valueParser = (params) => {
return this.lookupKey(config.ComboData['columnNameHere'], params.newValue);
}
valueFormatter and params.value - used when ag-grid rendering the value.
valueParser and params.newValue - when you are updating the cell value.
and here looupValue and lookupKey functions from ag-grid doc and the sample
lookupValue(mappings, key:string) {
return mappings[key];
}
lookupKey(mappings, name) {
for (var key in mappings) {
if (mappings.hasOwnProperty(key)) {
if (name === mappings[key]) {
return key;
}
}
}
}

Related

How to search an array of objects obtained by axios for an id? Vue 2

I am trying to verify if the user is inside that list that I capture by axios, the issue is that I have used the FILTER option but it always returns undefined or [], being that if the user exists in that array.
I can't think what else to do, because I validate if it is by console.log() the variable with which I ask and if it brings data.
created() {
this.getStagesDefault()
this.getSalesman()
this.getStagesAmountByUser()
},
methods: {
async getSalesman(){
const { data } = await axios.get('salesman')
this.employees = data.data
},
getStagesAmountByUser(){
console.log(this.user['id'])
var objectUser = this.employees.filter(elem => {
return elem.id === this.user['id']
})
console.log(objectUser)
},
Console
Vue data
The method getSalesman is asynchronous, meaning that getStagesAmountByUser will start executing before getSalesman finishes.
Two ways to fix the problem:
Await the getSalesman method, but you have to make the created method async as well. Change the code as follows:
async created() {
this.getStagesDefault()
await this.getSalesman()
this.getStagesAmountByUser()
}
Attach a .then to the getSalesman function, and start the next one inside the .then. Change the code as follows:
created() {
this.getStagesDefault()
this.getSalesman().then(() => this.getStagesAmountByUser())
}
getSalesman is an async method. At the time of the filter, the array being filtered is still empty.
this.getSalesman() // this runs later
this.getStagesAmountByUser() // this runs right away
Have the methods run sequentially by awaiting the async method:
await this.getSalesman()
this.getStagesAmountByUser()
You can avoid the inefficient clientside filtering if you pass the id to the backend and only select by that id.
Additionally, created only gets called once unless you destroy the component which is also inefficient, so watch when user.id changes then call your method again.
Plus don't forget you must wrap any async code in a try/catch else you will get uncaught errors when a user/salesman is not found etc, you can replace console.error then with something which tells the user the error.
{
data: () => ({
employee: {}
}),
watch: {
'user.id' (v) {
if (v) this.getEmployee()
}
},
created() {
this.getEmployee()
},
methods: {
getEmployee() {
if (typeof this.user.id === 'undefined') return
try {
const {
data
} = await axios.get(`salesman/${this.user.id}`)
this.employee = data.data
} catch (e) {
console.error(e)
}
}
}
}

Match object inside object in jest

I'm testing a function to see if, when called, it will return the proper created list.
To start, I create the elements, using the createDesign.execute() functions. It's tested on another file and working.
Then, I call the function I want to test: listAllDesigns.execute() and store it's value in a variable.
If I console.log(list), it returns the full list properly.
In pseudocode, what I'd like to do is: Expect list array to have an element with the design object and, within it, a design_id that equals "payload3".
How should I write this test?
Is there a better way to do this? (other than checking if list !== empty, please)
it('should return a list of all designs', async () => {
// Create fake payloads
const payload1 = {
...defaultPayload,
...{ design: { ...defaultPayload.design, design_id: 'payload1' } },
};
const payload2 = {
...defaultPayload,
...{ design: { ...defaultPayload.design, design_id: 'payload2' } },
};
const payload3 = {
...defaultPayload,
...{ design: { ...defaultPayload.design, design_id: 'payload3' } },
};
await createDesign.execute(payload1);
await createDesign.execute(payload2);
await createDesign.execute(payload3);
const list = await listAllDesigns.execute();
// expect(list). ????
});
The easiest method would be a combination of expect.arrayContaining and expect.objectContaining like so:
expect(list).toEqual(
expect.arrayContaining([
expect.objectContaining({
design: expect.objectContaining({
design_id: "payload3"
})
})
])
);

How do I pull a nested object out of an array with an api request returned json?

I have an API that I am calling to return a query. This query's format cannot be changed to be easier to manipulate. It has a nested array within it that I need to associate with the data from the higher levels.
Specifically, I am trying to pull the higher level id field and and the "value" field within "column_values" and associate them with one another preferably within a new array. I feel like the answer is here but I just can't grasp how to pull the data in the correct format and associate it together. Most of the comment lines can probably be ignored, they are my other attempts at making the syntax work correctly. Sorry about the mess. I'm really new to this.
const axios = require('axios')
const body = {
query: ` query {boards(ids:307027197) {name, items {name id column_values(ids:lockbox_) {title id value text}}}} `,
}
console.log("Requesting Query....");
function getApi (callback){
setTimeout(function() {axios.post(`https://api.monday.com/v2`, body, {
headers: {
MY_API_KEY_DATA
},
})
.catch(err => {
console.error(err.data)
})
.then(res => {
var queried = res
var array = queried.data.data.boards[0].items
//console.log(queried)
//console.log(array)
console.log(array.length)
//console.log("Total Items:", array.length)
var i;
for (i = 0; i < array.length; i++){
callback(queried.data.data.boards[0].items)
//callback([(queried.data.data.boards[0].items[i].column_values[0])])
}
}, 0);
})
};
getApi(callback => {
console.log(callback)
//console.log(parsed)
//output for above
//{"name":"address","id":"1234","column_values":
//[{"title":"Lockbox#","id":"lockbox_","value":"\"31368720\"","text":"31368720"}]}
//console.log(JSON.parse(parsed))
//output for above
//[
// {
// name: 'address',
// id: '353428429',
// column_values: [ [Object] ]
// }
//]
});
setTimeout(function() {
console.log("Query Returned")},1000);
From your data, column_values is an array with objects in it. For an array, you will have to access it with the key. For your case, if your data is like
var data = {
"name":"address",
"id":"1234",
"column_values": [{"title":"Lockbox#","id":"lockbox_","value":"\"31368720\"","text":"31368720"}]
}
You can access the id of column_values as data.column_values[0].id

How to use equals in a FilterExpression for DyanmoDb API

I am having a lot of trouble scanning and then using FilterExpression to filter based on a single value. I have looked at the api documentation and other stack overflow questions, but am still having trouble figuring the proper syntax for this. Since I am also using react and javascript for the first time, this may be a problem with my understanding of those.
Below is what I am trying to use as a filter expression. uploadId is the field name in the Dynamo database table and event.pathParameters.id is the variable that should resolve to the value that the scan results are filtered on.
FilterExpression: "uploadId = :event.pathParameters.id"
Below is the code in within context:
import * as dynamoDbLib from "./libs/dynamodb-lib";
import { success, failure } from "./libs/response-lib";
export async function main(event, context, callback) {
const params = {
TableName: "uploads",
FilterExpression: "uploadId = :event.pathParameters.id"
};
try {
const result = await dynamoDbLib.call("scan", params);
if (result.Item) {
// Return the retrieved item
callback(null, success(result.Item));
} else {
callback(null, failure({ status: false, error: "Item not found." }));
}
} catch (e) {
callback(null, failure({ status: false }));
}
}
Thank you for your help!
Always use Expression with ExpressionAttributeValues. params should look like this.
const params = {
TableName: "uploads",
FilterExpression: "uploadId = :uid",
ExpressionAttributeValues: {
":uid" : {S: event.pathParameters.id} //DynamoDB Attribute Value structure. S refer to String, N refer to Number, etc..
}
};

Is there a way to use a variable for the field name in a find() in mongoose?

Say you have a very long generic function you want to use over multiple schemas, and each schema has a different name for the field you're querying (and possibly different type of value -- string, number, etc.)
function foo (field, value){
Model.find({field: value});
}
foo('idfoo', 'xx');
foo('idbar', 5);
I tried to do something like this as a proof of concept in mongoose and it seems it will only work if you use a variable for value, but you can't for field.
Is this impossible?
Just put the variable in []
function foo (field, value){
Model.find({[field]: value});
}
foo('idfoo', 'xx');
foo('idbar', 5);
You could use the built in where function, making the call to the function you've shown unnecessary:
Model.find().where(fieldName, value).exec(function(err, results) { });
And you could do more than one via chaining:
Model.find().where(field1, val1).where(field2, val2).exec(...)
It also can be rich, supporting nested properties and other operators:
Model.find().where('orders.total').gt(1500).exec(...)
function foo(field, value) {
var query = {};
query[field] = value;
Model.find(query)...
}
If you want to search by generic field, try the below code
import { Request, Response } from "express";
import Client from "../models/client";
const search = async (req: Request, res: Response) => {
try {
const keyword = req.query.keyword || "";
const field: any = req.query.field || "email"; // default field
let clients = await Client.find(
{ [field]: { $regex: ".*(?i)" + keyword + ".*" } },
);
if (clients?.length) {
res.status(200).send(clients);
} else {
res.status(200).send("no match");
}
} catch (error) {
res.status(500).send(error.message);
}
};
export default {
search,
};

Categories