Using a Formatter for the Currencies in SAPUI5 - javascript

I want to build my own formattor for displaying the amount as it should in the different currencies.
One could guess I use this solution I already know:
<t:template>
<Text text="{
parts: [
{path: 'amount'},
{path: 'currency'}
],
type:'sap.ui.model.type.Currency',
formatOptions: {
currencyCode: false
}
}"
</t:template>
the problem with this solution is I already show the currency in a seperate column and if I go with this solution it looks pretty ugly....
so I tried this one:
<t:template>
<Text text="{parts: [
{path: 'amount'},
{path: 'currency'}
],
formatter : '.formatter.currency'}"
/>
</t:template>
and my formatter function looks like this:
currency: function(amount, currency) {
var change = [];
change.push(amount);
change.push(currency);
var sInternalType = "";
var amount1 = new sap.ui.model.type.Currency();
amount1.formatValue(change, sInternalType);
return amount1;
}
Here I would guess I do something completely wrong, as English is not my first language I would probably assume I didnt understood the API References right, as they is stated this:
formatValue(vValue, sInternalType): any
Format the given array containing amount and currency code to an output value of type string. Other internal types than 'string' are not supported by the Currency type. If an source format is has been defined for this type, the formatValue does also accept a string value as input, which will be parsed into an array using the source format. If aValues is not defined or null, null will be returned.
Parameters:
{array|string} vValue the array of values or string value to be formatted
{string} sInternalType the target type
Returns:
{any} the formatted output value

If it is your intention not to show the currency symbol or code because you already show it elsewhere, you could simply set showMeasure to false, e.g.:
<Text xmlns:core="sap.ui.core"
core:require="{ CurrencyType: 'sap/ui/model/type/Currency' }"
text="{
parts: [
'amount',
'currency'
],
type: 'CurrencyType',
formatOptions: {
showMeasure: false
}
}"
/>
Not showing the currency code/symbol is a feature of the standard Currency type. You don't need to extend it.
Note: In case of OData V4, require the type sap/ui/model/odata/type/Currency instead.

If you want to use an custom formatter, you can define it in this way:
currency: function(amount, currency) {
var oCurrency = new sap.ui.model.type.Currency({
showMeasure: false
});
return oCurrency.formatValue([amount,curreny], "string");
}
But I would recommend to use the solution from jpenninkhof for your use case

Related

Prisma/React Query Dependent undefined type challenges

I would like to take the output of one query (a TRPC query on Prisma) and use this as the dependent input in a future query.
I followed the dependent documentation for React Query but running into type errors that the return of the first may possibly be undefined (e.g. product is possibly 'undefined'):
const { data: product } = api.product.getUnique.useQuery({ id: pid });
const options = api.option.getAll.useQuery(
{
product: product.productSize,
region: product.productRegion,
},
{ enabled: !!product }
);
Does the inclusion of enabled not already handle this? If not, what is the correct way to adapt for Typescript.
Just casting the product value as a boolean return any truthy value (f.e if product will be equal to {} it will still result in true, that means that product won't necessarily have the productSize or productRegion properties, I would change it first to:
{ enabled: !!product && product.productSize && product.productRegion }
If that doesn't fix the typescript error, you as a developer can know for sure that the values are actually there so what you can use the as keyword in typescript to tell it that you know for sure that the type is what you want it to be:
(In this example I assumed that the values are string but you can change it to number or whatever the true value of them are)
const options = api.option.getAll.useQuery(
{
product: product.productSize as string,
region: product.productRegion as string,
},
{ enabled: !!product && product.productSize && product.productRegion }
);

How to get latest documents from FaunaDB, based on timestamp?

Currently I store some data in FaunaDB every week. This is done using a cronjob. In my code I'm trying to fetch the documents from only the last two weeks. I'd like to use the timestamp to do so.
One of the documents to fetch:
{
"ref": Ref(Collection("weeklyContributors"), "350395411XXXXXXXX"),
"ts": 1670421954340000,
"data": {
...allMyDataFields
}
}
My code
const now = Date.now() * 1000;
const twoWeeksAgo = (Date.now() - 12096e5) * 1000;
console.log(now); //returns 1670493608804000
console.log(twoWeeksAgo); // returns 1669284008804000
// the stored document has a timestamp of 1670421954340000, so this should be in between [now] and [twoWeeksAgo]
await client.query(
q.Paginate(
q.Range(
q.Match(q.Index("get_weekly_list_by_ts")),
twoWeeksAgo,
now
)
)
);
This is a screenshot of the index I created in Fauna
Above code should fetch all documents where the timestamp's between now and twoWeeksAgo but it returns an empty array (so no documents match the query). Above code doesn't generate any errors, it does return a statuscode 200, so syntax should be fine. Why can't I fetch the document I gave in this example?
UPDATE
Found the solution for the index. The index should filter on Values, not Terms. Enter TS and Ref returns the document. BUt now I don't know how to get the corresponding document.
This returns an error
await client.query(
q.Map(
q.Paginate(
q.Range(
q.Match(q.Index("get_weekly_list_by_ts")),
twoWeeksAgo,
now
)
),
q.Lambda((x) => q.Get(x))
)
);
Changed index screenshot here
Congratulations on figuring out most of the answer for yourself!
As you deduced, the terms definition in an index specifies the fields to search for, and the values definition specifies the field values to return for matching entries.
Since you added the document reference to the values definition, all that you need now is to fetch that document. To do that, you need to Map over the results.
The following example uses Shell syntax, and involves sample documents that I created with a createdAt field recording the creation timestamp (since ts is the last-modified timestamp):
> Map(
Paginate(
Range(
Match(Index("get_weekly_list_by_ts")),
TimeSubtract(Now(), 14, "days"),
Now()
)
),
Lambda(
["ts", "ref"],
Get(Var("ref"))
)
)
{
data: [
{
ref: Ref(Collection("weeklyContributors"), "350498857823502848"),
ts: 1670520608640000,
data: { createdAt: Time("2022-12-01T17:30:08.633Z"), name: 'Fourth' }
},
{
ref: Ref(Collection("weeklyContributors"), "350498864657072640"),
ts: 1670520615160000,
data: { createdAt: Time("2022-12-07T17:30:15.152Z"), name: 'Fifth' }
}
]
}
Since your index returns ts and ref, notice that the Lambda function accepts both parameters in an array. The Lambda parameters have to match the number returned by the index. Then the Lambda calls Get to fetch the document.
In case you're wondering, here's the index definition that I used for my example:
> Get(Index("get_weekly_list_by_ts"))
{
ref: Index("get_weekly_list_by_ts"),
ts: 1670520331720000,
active: true,
serialized: true,
name: 'get_weekly_list_by_ts',
source: Collection("weeklyContributors"),
values: [ { field: [ 'data', 'createdAt' ] }, { field: [ 'ref' ] } ],
partitions: 8
}
My index is misnamed: I used the same name from your original query to help you correlate what is being used.
Note: there is no need to mask the document ID in a document that you share. It is only valid for the database containing the document.

DynamoDB Update ExpressionAttributeValues

Sample test data:
"suppliers" : [
{
"supplierName": "xxx supplier"
},
{
"supplierName": "zzz supplier"
}
]
Excerpt of UpdateItem Params:
ExpressionAttributeValues:{
":sA" : {L: [event.suppliers]}
// ":sA" : {L: event.suppliers}
}
I encounter "UnexpectedParameter: Unexpected key '0' found in params". I tried changing the formatting of the AttributeValues but I get other errors like "UnexpectedParameter: Unexpected key 'supplierName' found in params".
I need help properly defining a list AttributeValue. Note that the input sample test data may contain x number of supplierName objects and hence defining the keys (ie. '0', '1', etc) in the AttributeValue is also not an option. I also prefer not to use the documentClient version of UpdateItem.
ExpressionAttributeValues is about to set a value to the parameter of the update expression, for example:
dynamoDb.update({
TableName: ...,
Key: ...,
UpdateExpression: 'set suppliers = :suppliers',
ExpressionAttributeValues: {':suppliers': event.suppliers}
}
You have to provide the key to the record and then you can change the suppliers attribute.

Exporting to excel with proper cell formatting on ag-grid

When I export a table to excel using ag-grid's own exportDataAsExcel() the resulting excel contains dates as General data type instead of Date.
[]
I have used this:
exportDataAsExcel({
processCellCallback: ({col, val}) => {( /*date value formatting here*/ )}
})
to format both Date, string with proper date formatting (DD/MM/YYYY) but I can't make excel properly recognize these cells as Date instead of General
This is reproducible with the excel export examples on their website: https://www.ag-grid.com/javascript-grid-excel/?framework=all#gsc.tab=0
I've used this code to apply value formatter in excell as well:
this.gridOptions.api.exportDataAsExcel({
processCellCallback: (params) => {
const colDef = params.column.getColDef()
// try to reuse valueFormatter from the colDef
if (colDef.valueFormatter) {
const valueFormatterParams: ValueFormatterParams = {
...params,
data: params.node.data,
node: params.node!,
colDef: params.column.getColDef()
};
return colDef.valueFormatter(valueFormatterParams);
}
return params.value;
},
});
You need to do three things:
When instantiating the Ag-Grid, you need to add (thanks to another user's answer elsewhere)
let excelStyles = [
{
id: "ExcelDateTime",
dataType: "dateTime",
numberFormat: { format: "yyyy-mm-dd hh:mm:ss;;;" }
},
{
id: "ExcelDate",
dataType: "dateTime",
numberFormat: { format: "yyyy-mm-dd;;;" }
}
];
...
<AgGridReact
... //such as rowData={rowData}
excelStyles={excelStyles}
...
/>;
For columns that are dates:
colDef.cellClass = "ExcelDateTime";
or
colDef.cellClass = "ExcelDate";
as appropriate, and
in your processCellCallback, format the date as an ISO date: "yyyy-mm-ddTHH:MM:ss"
Assuming that you are in control of the server-side application, I have found it easier to do the export from the server-side for any non-trivial exports / formatting.
By doing it on the server, you are in complete control of the data and the production of the Excel file, and not dependent on the limits of Ag-Grid's implementation.

formatting bound property in javascript before it is displayed

I'm trying to format a JSON date to a JavaScript date to display it in a nice way. The original date comes from a JSON-object, which looks like this:
{
"name": "foo",
"num": "1",
"date": "\/Date(1367539200000)\/"
}
The place where the JSON elements should be displayed later is a SAPUI5 object header:
objectHeader = new sap.m.ObjectHeader({
title: "{/name}",
number: "{/num}",
attributes: [
new sap.m.ObjectAttribute({
text: "{/date}"
})
]
});
Since the JSON object is bound to the object header via
dataModel.setData(json)
objectHeader.setModel(dataModel)
the values are correctly substituted. But i want to have the date correctly formatted to a more readable format instead of seeing /Date(1367539200000)/ on my website. I tried with
new sap.m.ObjectAttribute({
text: new Date(parseInt("{/date}".substr(6))).toLocaleString('de');
})
But that failed with an 'Invalid Date'. What would be the right syntax to format the JSON date to a Javascript data object in a model binding?
You can use a formatter to do that for you. The advantage is that you can properly use databinding, so your controls will be updated automatically in case the model changes.
new sap.m.ObjectAttribute({
text: {
parts: [
{path: "/date"}
],
formatter: function(date){
//do whatever you want
return /* the value you want to have as result */;
}
}
})

Categories