I want to sync an element with an array property with the local storage by using an app-localstorage-document. What's the best way to do this a the app-localstorage-document supports only objects and not arrays to bind to the data property?
Should I implement my own app-localstorage-document implementation?
Can I use another mechanism that wraps the array into an object and back?
for example:
Thanks for the ideas!
Note that the Local Storage is a key-value database, so you can not store an array without a key in such database. if you want to store your array, you can use a computed property to build the object from your array:
objectToStore: {
type: Object,
computed: 'computeObject(myArray.splices)'
}
And in your compute function generate the object:
computeObject: function(){
return {
someKey: this.myArray
}
}
And then bind objectToStore to your app-localstorage-document element.
The problem doesn't seemed to be the storage of an array. I used the app-local-storage in a Polymer test in the setup with a fixture. The setup (also async) doesn't wait until the app-local-storage is completely initialized and this caused some side effects. Adding a call to "getStoredValue(...)" and sync on this call seemed to be a workaround.
Related
I have an array in Mule that I am iterating over. I believe the for each makes a copy of the array I pass it and iterates through that. Is it possible to access that copy by reference and modify it? Based on certain conditions I would like to add extra elements to the array. I have tried to use vars.rootMessage but it does not give me what I am expecting.
No. Just create a new array in a variable and add to it. To provide more context, Mule 4 variables live in Mule Events, which are immutable. That means that a change results in the creation of a new event.
I'm passing a Laravel Model's dataset to a vuejs2 component via ajax/ axiom and rendering it fine.
However, there is a JSON column in the model which stores a valid json object, the data could look like so: {'key':'value'} and it's worth noting that I'm working with it without issue in Laravel Controllers etc thanks to a Mutator on the Model ( protected $casts = [ 'the_json_column' => 'array']; )
When I pass this model to vuejs via axiom / ajax all of the properties in the array behave as usual, I can iterate over them and render them in the vuejs2 component DOM.
Until I interact with 'the_json_column' which despite Laravel's mutator is being passed to vuejs2 as a string, e.g. "{'key':'value'}"
Is there a more elegant way than doing a JSON.parse(data.the_json_column).key in my vuejs2 component every time I want to interact with the JSON column data?
The solution I've gone with is decoding the data property manually in the VueJS2 template,
e.g. JSON.parse(data.key_which_is_actually_json).property_in_the_object
Any laravel based code (accessors, mutators etc) will fail when the property is transferred to VueJS2 component over HTTP as VueJS2 isn't smart enough to check properties in data receive and decode them.
VueJS2 seems to only decode the top level of properties in data received.
You may create your own Accessor and then convert the column to an array manually before retrieving the model.
public function getTheJsonColumnAttribute($value)
{
return json_decode($value, true);
}
While it may seem laravel simply treated that column as a mere 'string' value when coming out, you can further validate that there is indeed a conversion.
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
I got an anonymous array which I want to deserialize, here the example of the first array object
[
{ "time":"08:55:54",
"date":"2016-05-27",
"timestamp":1464332154807,
"level":3,
"message":"registerResourcePath ('', '/sap/bc/ui5_ui5/ui2/ushell/resources/')",
"details":"","component":"sap.ui.ModuleSystem"},
{"time":"08:55:54","date":"2016-05-27","timestamp":1464332154808,"level":3,"message":"URL prefixes set to:","details":"","component":"sap.ui.ModuleSystem"},
{"time":"08:55:54","date":"2016-05-27","timestamp":1464332154808,"level":3,"message":" (default) : /sap/bc/ui5_ui5/ui2/ushell/resources/","details":"","component":"sap.ui.ModuleSystem"}
]
I tried deserializing using CL_TREX_JSON_SERIALIZER, but it is corrupt and does not work with my JSON, here is why
Then I tried /UI2/CL_JSON, but it needs a "structure" that perfectly fits the object given by the JSON Object. "Structure" means in my case an internal table of objects with the attributes time, date, timestamp, level, messageanddetails. And there was the problem: it does not properly handle references and uses class description to describe the field assigned to the field-symbol. Since I can not have a list of objects but only a list of references to objects that solution also doesn't works.
As a third attempt I tried with the CALL TRANSFORMATION as described by Horst Keller, but with this method I was not able to read in an anonymous array, and here is why
My major points:
I do not want to change the JSON, since that is what I get from sap.ui.log
I prefere to use built-in functionality and not a thirdparty framework
Your problem comes out not from the anonymity of array, but from the awkwardness of SAP JSON (De)serializer, which doesn't respect double quotes, which enclose JSON attributes. The issue is thoroughly described in this answer.
If you don't want to change your JSON on-the-fly, the only way you have is to change CL_TREX_JSON_DESERIALIZER class like this.
/UI5/CL_JSON_PARSER parses JSONs with unknown format.
Note that it's got "for internal use" written on it so many times that you probably should take it seriously and clone its code to fixate it.
I need to pass data between views in my client-server app. For simple string value, I can put them as attributes on the target element and read the value when the select event is triggered on it. From there, I can pass this string value onto the next document pretty easily.
But the problem comes with much more complex data that's in JSON format. I tried doing JSON.stringify(myData) and putting this value in an attribute. But the compiler doesn't like the { in this attribute value.
I could probably try escaping all the different characters that the compiler has problems with. But I don't think that's a good idea.
Is there any way of implementing jQuery's .data() functionality in TVML and TVJS ? Or is there any other way that makes sending data between views a possibility ?
You can pass your data as URL parameters. Then in the new view, get them using Javascript.
EDIT: And I see in the comment above you came to a similar conclusion.
You could keep your data in a semi-global associative array. Store the key in an attribute on the element and use that to get your data structure.
Ex:
var globalData;
function onSelect(e){
var id=e.target.getAttribute("id");
var specificData=globalData[id];
}