Different values for same object member in Angular - html

the following function receives an event from the Angular Material Design DatePicker and shall print it to the console:
applyFilter(event: MatDatepickerInputEvent<Date>) {
console.log(`${event.value}`); // prints the selected date
console.log(event.value); // prints some weird object
}
But they are each printing a different output to the console.
The first prints the actual selected date, the second one prints some weird object to the console.
This is the console output:
This is my DatePicker:
<mat-form-field>
<mat-label>Anfangsdatum</mat-label>
<input matInput (dateInput) = "applyFilter($event)" [matDatepicker] = "startDatePicker">
<mat-datepicker-toggle matSuffix [for]="startDatePicker"></mat-datepicker-toggle>
<mat-datepicker #startDatePicker></mat-datepicker>
</mat-form-field>
I just want to get the date the user picked using the DatePicker from Angular Material Design, but it seems like that this overly complicated. Can someone please help me?

You are seeing two different values.
When you call console.log(new Date()) you will get the actual date object. (replace new Date() with any date object such as your event.value)
This object is the weird object that you speak of. It's simply a Date which has all kinds of methods available to help you. But in the end, all a Date is actually is a Number that represents milliseconds since 1 January 1970 UTC, then a bunch of helper functions with it.
One of those helper functions is .toString().
When you call console.log(`${new Date}`); you are creating a date object, then putting it inside a template literal (the backticks). This template literal calls the .toString() of the date object to convert it to a string, as you are asking for a string with a template literal. So you get the string representation of the Date object. (It's actually a bit more complex than that per this post, it's not always the toString() method per this post).
So if you want the string value, use the template literal or just call event.value.toString(). If you want the date object so you can do things with it (use the full date object and all its abilities per the documentation linked at the top)... use the date object. If you have other questions, feel free to comment.
Edit:
I don't think it's the actual date object. Check out the API. You are getting the object you are expecting, but it may be the one described in this API. I noticed they both have the add method in the prototype. Either way, it's an object vs the string representation. I tried to find the type definition since I'm assuming you are in Typescript, that should list all the methods available to you.

Related

Can I create a custom field with datatype as sobject in the Salesforce platform event?

In the platform event, I only see custom field datatypes with Text, Date, Check​box and Number, but not an sobject type. I need to serialize my own class inst​ance (which has accounts + contact list) and publish the object in json format.
I tried creating a custom text field (with name data__c) and assigned the json serialized object to this field. But, the receiver side is getting the unnecessary quote since it's a string. I want to avoid that and just publish as an object only, can I do that?
Now, at the receiver side the data__c is coming like start and ends with double quotes instead of just an object (which starts with curly brackets) like as follows:
enter image description here
So, one option is the receiver should take these quotes out and treat this as an object or other option sending it like an object itself. Request is, can we send as an object? Please help me here.
Thanks
// custom classes defined for json serialization
class CustomAccount {
String oper;
List<Account> accountList;
List<CustomContact> custContactList;
}
// creating an object
customAccount ca = new CustomAccount();
// My new platform event, with assigning the json serialized data to data__c which a text field
Pltf_Notifications__e eve = new Pltf_Notifications__e();
eve.data__c = json.serialize(ca);
enter code here
You can't create sobject data type for platform events. You can handle the logic from platform trigger if response has sobject type by deserializing the sobject data type. If it matches, you can call other handler classes from here by passing the sobject data and construct your desired format from here, then fires the platform event.

Parsing query string in Node to allow logical operators

I would like something similar to what node-odata offers, but I do not want to wrap it around my database (I am using Cassandra and already have an Express app set up with routes, etc).
Currently, I grab data from the database (which will ultimately return a JSON object to the user) and then using the values passed in the query string I modify the results with JavaScript and pass the modified JSON object on through to the user.
I cannot pass in a query string like this http://localhost:3001/getSomeData?name=jim&age=21||eyeColor=red which includes logical operators in the query string, and would grab all data and filter it where the name is "jim", the age is "21" OR eyeColor is "red". So this would give me all Jims that have either eyeColor red and/or age of 21. If I used this age=21&&eyeColor=red I would expect to get all Jims that have BOTH eye color of red and are 21 years old.
I was thinking of using a custom query string that can be passed in (i.e. inclusive=age&inclusive=eyeColor appended at the end of the query string) and in Node, I would modify the filter results to treat these properties (age and eyeColor) as if they were passed in with the || OR operator). However, this is quite verbose, and I was hoping there was a library or another simpler implementation out there that solves this problem, or somehow lets me pass in simple logical operators into the query string.
I ended up using this library to achieve what I wanted: https://www.npmjs.com/package/jspath
It's well document and worked perfectly for my situation.
npm i querystringify //or
https://cdnjs.cloudflare.com/ajax/libs/qs/6.7.0/qs.min.js
//it will will return an object
const myObject = Qs.parse(location.search, {ignoreQueryPrefix: true});
//you can use object destructuring.
const {age,eyeColor}=Qs.parse(location.search, {ignoreQueryPrefix: true})
By default, parsing will include "?" too.
{ignoreQueryPrefix: true} this option will omit "?".

TypeScript types serialisation/deserialization in localstorage

I have a Typescript app. I use the localstorage for development purpose to store my objects and I have the problem at the deserialization.
I have an object meeting of type MeetingModel:
export interface MeetingModel {
date: moment.Moment; // from the library momentjs
}
I store this object in the localStorage using JSON.stringify(meeting).
I suppose that stringify call moment.toJson(), that returns an iso string, hence the value stored is: {"date":"2016-12-26T15:03:54.586Z"}.
When I retrieve this object, I do:
const stored = window.localStorage.getItem("meeting");
const meeting: MeetingModel = JSON.parse(stored);
The problem is: meeting.date contains a string instead of a moment !
So, first I'm wondering why TypeScript let this happen ? Why can I assign a string value instead of a Moment and the compiler agree ?
Second, how can I restore my objects from plain JSON objects (aka strings) into Typescript types ?
I can create a factory of course, but when my object database will grow up it will be a pain in the *** to do all this work.
Maybe there is a solution for better storing in the local storage in the first place?
Thank you
1) TypeScript is optionally typed. That means there are ways around the strictness of the type system. The any type allows you to do dynamic typing. This can come in very handy if you know what you are doing, but of course you can also shoot yourself in the foot.
This code will compile:
var x: string = <any> 1;
What is happening here is that the number 1 is casted to any, which to TypeScript means it will just assume you as a developer know what it is and how you to use it. Since the any type is then assigned to a string TypeScript is absolutely fine with it, even though you are likely to get errors during run-time, just like when you make a mistake when coding JavaScript.
Of course this is by design. TypeScript types only exist during compile time. What kind of string you put in JSON.parse is unknowable to TypeScript, because the input string only exists during run-time and can be anything. Hence the any type. TypeScript does offer so-called type guards. Type guards are bits of code that are understood during compile-time as well as run-time, but that is beyond the scope of your question (Google it if you're interested).
2) Serializing and deserializing data is usually not as simple as calling JSON.stringify and JSON.parse. Most type information is lost to JSON and typically the way you want to store objects (in memory) during run-time is very different from the way you want to store them for transfer or storage (in memory, on disk, or any other medium). For instance, during run-time you might need lookup tables, user/session state, private fields, library specific properties, while in storage you might want version numbers, timestamps, metadata, different types of normalization, etc. You can JSON.stringify anything you want in JavaScript land, but that does necessarily mean it is a good idea. You might want to design how you actually store data. For example, an iso string looks pretty, but takes a lot of bytes. If you have just a few that does not matter, but when you are transferring millions a second you might want to consider another format.
My advise to you would be to define interfaces for the objects you want to save and like moment create a .toJson method on your model object, which will return the DTO (Data Transfer Object) that you can simply serialize with JSON.stringify. Then on the way back you cast the any output of JSON.parse to your DTO and then convert it back to your model with a factory function or constructor of your creation. That might seem like a lot of boilerplate, but in my experience it is totally worth it, because now you are in control of what gets stored and that gives you a lot of flexility to change your model without getting deserialization problems.
Good luck!
You could use the reviver feature of JSON.parse to convert the string back to a moment:
JSON.parse(input, (key, value) => {
if (key == "date") {
return parseStringAsMoment(value);
} else {
return value;
});
Check browser support for reviver, though, as it's not the same as basic JSON.parse

Typescript String Based Enums

So I've read all the posts on String Based Enums in Typescript, but I couldn't find a solution that meets my requirements. Those would be:
Enums that provide code completion
Enums that can be iterated over
Not having to specify an element twice
String based
The possibilities I've seen so far for enums in typescript are:
enum MyEnum {bla, blub}: This fails at being string based, so I can't simply read from JSONs which are string based...
type MyEnum = 'bla' | 'blub': Not iterable and no code completion
Do it yourself class MyEnum { static get bla():string{return "bla"} ; static get blub():string{return "blub"}}: Specifies elements twice
So here come the questions:
There's no way to satisfy those requirements simultaneously? If no, will it be possible in the future?
Why didn't they make enums string based?
Did someone experience similar problems and how did you solve them?
I think that implementing Enum in a C-like style with numbers is fine, because an Enum (similar to a Symbol) is usually used to declare a value that is uniquely identifiable on development time. How the machine represents that value on run time doesn't really concern the developer.
But what we developer sometimes want (because we're all lazy and still want to have all the benefits!), is to use the Enum as an API or with an API that does not share that Enum with us, even though the API is essentially an Enum because the valid value of a property only is foo and bar.
I guess this is the reason why some languages have string based Enums :)
How TypeScript handles Enums
If you look at the transpiled JavaScript you can see that TypeScript just uses a plain JavaScript Object to implement an Enum. For example:
enum Color {
Red,
Green,
Blue
}
will be transpiled to:
{
0: "Red",
1: "Green",
2: "Blue",
Blue: 2,
Green: 1,
Red: 0
}
This means you can access the string value like Color[Color.Red]. You will still have code completion and you do not have to specify the values twice. But you can not just do Object.keys(Color) to iterate over the Enum, because the values exist "twice" on the object.
Why didn't they make enums string based
To be clear Enums are both number and string based in that direct access is number and reverse map is string (more on this).
Meeting your requirement
You key reason for ruling out raw enums is
so I can't simply read from JSONs which are string based...
You will experience the same thing e.g. when reading Dates cause JSON has no date data type. You would new Date("someServerDateTime") to convert these.
You would use the same strategy to go from server side enum (string) to TS enum (number). Easy done thanks to the reverse lookup MyEnum["someServerString"]
Hydration
This process of converting server side data to client side active data is sometimes called Hydration. My favorite lib for this at the moment is https://github.com/pleerock/class-transformer
I personally handle this stuff myself at the server access level i.e. hand write an API that makes the XHR + does the serialization.
At my last job we automated this with code generation that did even more than that (supported common validation patterns between server and client code).

dijit Form toJson returns empty object for dijit.form.DateTextBox

Running the following code:
dojo.toJson(formSearch.attr("value"));
Appears to not serialize the value of dijit.form.DateTextBox controls. Looking in Firebug, I can see that formSearch.attr("value")) returns the appropriate DOM object that contains the value that the control is set to, but when I try to serialize it, I get something like:
{"startDate":{}}
The value attribute of a dijit.form.DateTextBox is of type Date. This is useful to manipulate Dates from JavaScript, but by default there is no serializer for Dates to JSON. If you wish to get the value of the widget for serialization, use dijit.form.DateTextBox.serialize(), which will give you the value as a string.
If you use the DateTextBox in a or a dijit.form.Form, the serialization should happen for you on submit.