Dart has a known error where a class you create with public variables can not be passed into native JSON template calls. I was not sure if there has been any improved headway on this.
Example;
class Test{
String a;
int b;
}
would be nice to translate into:
{"a":"","b":0}
It seems when looking around the internet and forums for dart, this was an issue, and with a language that works so closely with Javascript, a terribly large oversight. I havent seen anything yet, though it seems you might be able to scrape a the public variables if you are using mirrors, which is seemingly time intensive.
Here is what a sample is that I am working on.
class UserGroup{
String a;
int b;
UserGroup.fromMap(Map m){ ... }
}
I receive from a Service call, a map which is cast to a UserGroup.
This will then produce a List which are binded and passed into a sub WebComponent which will access a Map. Something like this.
<service-call result="{{rowData}}"></service-call>
<grid-creator rows="{{rowData}}"></grid-creator>
and inside of grid creator:
<dom-module id="grid-creator>
<template>
<div>
<template is="dom-repeat" for="{{rows}}" as="row">
<div id="{{row.id}}">{{row.name}}</div>
</template>
</div>
</template>
</dom-module>
The issue had has is that the grid-creator is dynamic, accepting a row of maps and parsing accordingly. Even if I were to say List<UserGroup> rows it doesnt understand it as row and will throw an error like:
type 'UserGroup' is not a subtype of type 'Map' of 'row'
That means that Dart classes nativly cannot interact with template repeaters at all, unless the class itself is a subtype of map. which wouldnt make sense to me.
That being said, a lot of the notes are from September 2015 and prior. I was curious where this has progressed.
You could say: Well, why not just have a toJson method which turns a map, then parse and intercept the class and convert it before it it hits the template.
I mean, i guess that could be a thing if i do an observer on the rowData and then have a second variable which is populated and subsequently refresh the grid-creator but that that isnt really the point. It sort of removes the Object from being passed around and at that point, I should just remove the class component and just use maps. If im just using maps, then why the heck would i use dart? /endrant
Anyways, has there been improvements in this area?
One of the threads i was reading about serialization: https://github.com/dart-lang/sdk/issues/16630
Edit: I was trying to look into the concept of having the class UserGroup extend JsProxy, but i dont think that would resolve the issue i was having
Related
So, I am building a map using angular and leaflet. One of the things that I use is leaflet.markercluster. When i click on the cluster I want the popup content of a random marker of a cluster to be written somewhere. To access the popup content of some random cluster I did this:
cluster.getAllChildMarkers()[0]._popup._content
and got an error: Property '_popup' does not exist on type 'Marker'.
But the thing is, if I do ng serve first time it failes to compile, but if I change anything and save all it compiles sucessfully with the errors and I can see the content of the popup.
Also, if I do console.log(cluster.getAllChildMarkers()[0]) and I inspect element on webpage I get the regular console log of a marker with latlng andall other atributtes, including _popup.
Does anybody know why does typescript/vscode log an error, but html console sees it normally?
Because TypeScript is more strict than JavaScript, it warns you of potential issues that may actually work just fine once transpiled in JS.
In this specific case, this is simply due to the pseudo private properties ("_popup" follows the usual JS libraries convention of using an underscore _ prefix to denote pseudo private members) not being declared on the TS types of Leaflet, since you are not expected to use them.
But of course this is still technically valid in JS, so you can tell the TS compiler "I know what I am doing" by using the //#ts-ignore comment directive just above that line.
Or longer but much better, since you can remain under TS watch: use actual Leaflet API to achieve what you are doing:
getPopup() method
getContent() method
cluster.getAllChildMarkers()[0].getPopup()?.getContent()
I have a simple page with an input element that has a DOM event (input). The HTML page also calls a function that just outputs something via console.log. Now when I open the page, it will show the log, but when I type something into the input field, it will also trigger the function EVERY time I type something.. (Actually, when I type a letter, it will console.logs TWICE every time)
Why does this happen? How to prevent it? I read some things about changeDetection, but is there another solution?
HTML:
{{test()}}
<input class="input-msg" [value]="textValue" (input)="textValue = $event.target.value;">
.ts:
export class TestComponent implements OnInit {
constructor() {
}
test() {
console.log('test message');
}
}
Expected Behavior:
The {{test()}} should not be called when typing something into the input field
Since you're calling a function in one of the data-binding syntaxes, whenever Angular performs Change Detection, it will call this method.
Before for a function, anything that cases is the value that it returns. And for Angular to know that the returned value has changed, Angular will have to run it.
This is the exact same issue that people have raised a several questions here:
Angular: Prevent DomSanizer from updating on DOM Events
Angular performance: ngStyle recalculates on each click on random input
Angular 7 ,Reactive Form slow response when has large data
You might want to read through these threads to understand what's going on here and how you can fix this issue.
The solution is to basically design your implementation in such a way, that it never calls a method in one of the data-binding syntaxes, i.e.
In String Interpolation - {{ methodCall() }}
In Property Binding - [propertyName]="methodCall()"
In Attribute Binding - [class.className]="methodCall()" / [style.style-name]="methodCall()"
An alternative solution is do move this code to a Child Component and configure the changeDetectionStrategy on that child component to ChangeDetectionStrategy.OnPush
I'm a bit amazed I haven't been able to find an explanation for how to do this as it seems like it's fairly elemental to debugging, but I can't find anywhere how to print the attributes of an object in Polymer.
I'm learning Polymer and I keep running into situations where I have an object, but I have no idea what the attributes are of the object. (Ex. I print to the window, and I get [object Object]. I've found some explanations for how to print a list of the keys/attributes of an object (I know how to print the values for those keys if I know what they are), but I have no idea how to get the keys if I don't already know the format of my data. Every example presumes you already know what the attributes are.
I've seen solutions recommending adding a script like:
getKeys : function(o){
return Object.keys(o);
}
And then they recommend something like this:
<template is="dom-repeat" items="{{ item in obj | getKeys}}">
{{item}}
</template>
But I think they must work off maybe an earlier version of polymer. Most are from 2014-ish and I know the library has changed a lot since then.
This is the closest thing I get to an error with this code:
Polymer::Attributes: couldn`t decode Array as JSON
Here's an example post recommending this strategy. I understand I could dig deeper into the documentation and try to understand what response is supposed to be coming back, but I'm more curious what the general strategy is for this situation - I've multiple times wanted to check to see how polymer was modeling something vs how I thought it was.
The post you mention recommends a method that is no longer possible with post-1.0 Polymer, which does not support that syntax of filtering/pipes (as of the current release, 1.5.0).
You could use DevTools to select the Polymer element and then run console.dir($0). This works in the following browsers (and maybe older versions):
Chrome 50
Firefox 45
Safari 9.1
Opera 39
Chrome and Opera display all keys (even inherited ones from HTMLElement) in sorted order, so it can be tedious to scan through the long list of keys for a Polymer-specific property. However, Firefox and Safari list Polymer-specific keys first and then the inherited ones.
One workaround for Chrome/Opera is to use this snippet:
((o) => {
let obj = {};
Object.keys(o).sort().forEach((x) => {
obj[x] = o[x];
});
console.dir(obj);
})($0);
Here's a codepen that logs the attributes of a paper-button. You don't need to click the button. Open the browser's console log (not the Codepen console) to see something like the screenshot below. You can expand the fields in the console log to see the attributes of the Polymer object.
The solution I have been using is the following:
Place a button somewhere on the visible page.
When that button is tapped, print the object to the console.
my-element.html
<button on-tap="show">Click here to see user</button>
...
show: function() {
console.log('user', this.user);
},
...
You can also use console.dir() as follows.
<my-element id="foo"></my-element>
...
bar: function() {
console.dir( this.$.foo );
}
I can get my <iron-meta> instance to work properly when using a static value. But when I bind the value to a dynamic variable (using {{}}) it <iron-meta> no longer behaves as expected.
Does <iron-meta> support binding its value to dynamic variables?
<iron-meta id="meta" key="info" value="foo/bar"></iron-meta> // works
<iron-meta id="meta" key="info" value="{{str}}"></iron-meta> // fails
Previous work
This question is a refinement of this question in order to clarify that the ONLY thing causing the problem is the change from a static string value to a dynamic string value binding. I was getting a lot of other suggesting that had nothing to do with the change from static to dynamic so I thought it might be best to rewrite the question to clarify that. But the entire code context is contained in the links there if that would help.
Alternative solutions
There has been some recent chatter about using <iron-localstorage>. Perhaps that is the best way to go for dynamic binding essentially creating global variables?
Yes, <iron-meta> does support binding to variables, but perhaps not in the way you think.
Example: http://plnkr.co/edit/QdNepDrg9b3eCTWF6oRO?p=preview
I looked through your code here, here, and here but I'm not entirely clear what your expectations are. Hopefully my attached repro might shed some light. I see you have declaratively bound <iron-meta id="meta" key="route" xvalue="foo-bar" value="{{route}}"></iron-meta> which is fine - when route changes, iron-meta's key="route" will update accordingly.
However, be aware that in Polymer 1.0, <iron-meta> is in essence a one-way bind from parent to child in the sense that you set a meta key value dynamically by binding to a property; but to get that value, you'll have to get it imperatively via iron-meta's byKey() method.
<iron-meta> is just a simple monostate pattern implementation without an in-built path notification mechanism. What this means is value changes do not propagate upwards. Therefore, doing something like
<!-- this does not work like the way you think -->
<iron-meta id="meta" key="foo" value="{{bar}}">
in order to get the value of foo, or listen to changes to foo, does not work. This behaves more like a setter, where you set the value of foo based on your data-bound property bar.
From what I gather, it seems that you're trying to implement some sort of global variable functionality. A monostate implementation used to work in Polymer 0.5, but not in 1.0. Unfortunately, until Google endorses a "best-practice" pattern for this, suggestions till-date seems a bit speculative to me. You might find this (Polymer 1.0 Global Variables) helpful.
I have had success using <iron-signals> to communicate global information. I know there is a warning in the <iron-signals> documentation that discourages its use for related elements, but when broadcasting a shared resource it seems just the thing. For example:
// source element
var db = SomeDB.init();
this.fire('iron-signal', { name: 'database', data: db });
<-- sink element -->
<iron-signals on-iron-signal-database="dbChange"></iron-signals>
class SinkElement {
dbChange(e, detail) {
this.db = detail;
this.db.getSomeData();
}
}
I am using the URL logic for creating a dynamic Tree in Flex using action script. However the output is not properly shown (Object name is shown instead of Label).
Code is available in above mentioned URL.
Please help.
Write a correct toString() implementation of your DataTreeNode, so it would have a proper display in this tree.
An example: Provided the class DataTreeNode has a data:Object field, and this object has a urlToDisplay:String property that you want displayed. Do like this:
override public function toString():String {
if (!data) return '[null]';
return data.urlToDisplay;
}
If you only rely on simple Objects or data classes, you can use the tree's labelField or labelFunction in order to read and/or format data, which is passed to the renderer. There are no new item renderer classes needed.
New renderer should be compatible with these functions!
On a site note: item renderer are not "mostly just simple MXML classes", they are component instances. It doesn't matter how there are implemented. There are best practises like avoiding data bindings in item renderers, that's why it is common to use the markup for drawing, but implementing the views behaviour according to the Flex component live cycle. you might want to read about it in the documentation, because it is a necessary read for a Flex developer.
You will have to write an ItemRenderer that tells your tree how it should display the components. ItemRenderers are mostly just simple MXML classes that access one item each and display the data in any way you want. You will have to assign the ItemRenderer to your component.
See this article:
http://help.adobe.com/en_US/flex/using/WS03d33b8076db57b9-23c04461124bbeca597-8000.html