I have a custom polymer-element, "my-app" which uses template if="..." constructs to conditionally include other polymer elements.
All of these polymer elements are defined in one file, "views.html". This file includes the Dart code to implement all these custom elements, "views.dart".
I have a separate "index.html" that does nothing more than import the "views.html" file along with the standard polymer and dart initialization files, and then place a single my-app declaration tag in the body.
I am finding that the ".created" constructors for 1) the various subelements and 2) the my-app element itself (that conditionally includes subelements) are being called multiple times - even though a my-app element is declared only once in the simple "index.html" file.
I can see it right in the debugger.
Particularly regarding the calling of "MyApp.created", I thought this might be some garbage collection issue. But I set a global variable the first time MyApp is created to the MyApp instance to preclude this.
What is even stranger to me is that when MyApp is created repeatedly again, I can see that the global variable (to prevent gc of a MyApp instance) has been reset to "null", as if the entire file of Dart code had been reloaded/reevaluated somehow.
Very strange to me.
Are the PolymerElement subclasses for custom elements instantiated merely for the definition of custom elements? If so, that would be odd. I would think such custom polymer element subclasses would only be instantiated during the declaration of polymer elements.
Also, would a template conditional inside a polymer element definition somehow be able to force reconstruction of a the defined polymer element? This is hard to imagine, but then anything is possible with Dart Polymer, LOL!!!
I was looking for an authoritative document on when constructors for custom Dart PolymerElements might be called, but I could find no such document.
Any and all help greatly appreciated.
Related
In an attempt to develop a global AST transformation to add a new method to an Enum class within my app, I've set up this example project using Grails 5.
https://github.com/davebrown1975/grails_enum_experiment
The expected behaviour is that on compilation/building, the AST transform will be applied to the single enum class in the project ('tst.ExampleEnum'). I can see the 'visit' method being called in my Transformer ('tst.EnumTranslationTransformation'), however the sourceunit ast classes passed as a parameter to the visit method never include my Enum class.
Once the app is running however, if I make the simplest change to the Enum class, e.g. pressing space somewhere and saving it to trigger compilation and reloading, then this time I will see output in the console informing me the visit method was called AND the enum class was detected and AST has been applied.
Things I've tried, as per Grails docs, established the transforming class in it's own 'plugin', putting the class into a sub package of org.grails.compiler. Neither of these made a difference and I didn't see the AST being called at ever until I referenced the EnumTranslatorTransformation class from within a new file META-INF/services/org.codehaus.groovy.transform.ASTTransformation
Any thoughts as to what I'm missing here would be greatly appreciated.
The solution I found that ensures the AST is compiled and applied to the Enums at build time was to place the transformation into an inline plugin. What was critical at this point was to ensure that the META-INF/services/org.codehaus.groovy.transform.ASTTransformation file was moved to the plugin and not the main app. Only then would I see the transformation applied after a clean and build of the project.
I've been experimenting with the dynamic component loader in Angular2. An issue, possibly related to this: https://github.com/angular/angular/issues/4330 , seems to be that once a component is loaded with, say, the loadIntoLocation() function, the injector cannot find the parent component's injector or the things that were injected into it. As that article suggests, you can pass an array of Resolved Providers obtained from the parent's injector (Injector.resolve) into the last parameter of loadIntoLocation().
This seems to work initially, but I have also found that any children of the dynamically loaded components also have the same problem. The injector of the children does not know to look up the injection tree for providers, so a standard injection in the constructor of the children like
constructor( myComponent: MyComponent)
does not work. The children (of the dynamically loaded components) are not dynamically loaded but just "normally" instantiated using a template, selector etc. I am wondering:
Is this (still) a known issue or am I misunderstanding anything?
If a known issue is there any workaround at the child level? I tried a constructor as above and also using #Host and also using forward ref + #host but none work. Is there another way to manually pass bindings to a component that is not dynamically loaded?
Is there any other possible workaround for this?
The problems seems to be caused by the resolved providers passed to loadToLocation(). DI is hierarchical and DI tries to resolve required types by walking the hierarchy towards the root, but the chain is broken at loadToLocation() because there providers are passed instead of a child-injector.
The dynamically added component and its children can only resolve providers passed to loadToLocation() or listed in the providers list of the dynamically added component itself (or one of its children if it is a (grand-)parent of the actually resolved component).
When DI walks upwards from within the dynamically inserted tree to resolve a dependency, the iteration stops at the component added by loadToLocation() because the injector of this component doesn't have a parent injector (which would be the injector of the host component where the dynamically added component was added).
See also https://github.com/angular/angular/issues/5990
Correction on this. I have conflated another problem in my code with what I thought was the bug described above. The children of my dynamically loaded component were derived from abstract classes. I was trying to inject the abstract class into the children as opposed to the actual implementation which, per this
Interface based programming with TypeScript, Angular 2 & SystemJS
I have learned you cannot do. The injection tree does get broken upon a dynamic load (which I do think should be corrected), but I take back the part about the children thereafter not being able to traverse their own tree. Thanks for the comments - it helped me sort it out.
Is there a way to set up bindings imperatively. An example use case:
var el2 = new MyElement();
el2.myProp = this.$.anotherElement.anotherProp
That won't setup a binding, it just assigns the value or object. I'd like to find a way to do something like:
el2.myProp.bindTo(this.$.anotherElement.anotherProp)
Possible?
Polymer 1.0 does not support this at the moment - as explained by #kevinpschaaf in Github https://github.com/Polymer/polymer/issues/1778.
(comment by #kevinpschaaf)
No, we don't currently support this, outside of dom-bind, which is the
only template implementation that late-binds instance children. You
can document.createElement('template', 'dom-bind'), then you can
dynamically append children with binding annotations to its content,
and the bindings will only be evaluated once the dom-bind is attached
to the document. See tests here that show this usage of it:
https://github.com/Polymer/polymer/blob/master/test/unit/dom-bind.html#L95
Note that dom-bind does not currently allow binding to outer scope, so
it has limited use in custom element templates (it's main use case is
for binding between elements in the main document), and that's not
likely to change short-term.
We are achieving a lot of performance optimization by baking the
binding connections into the prototype at registration time for an
element (rather than at instance time), and we haven't built up enough
of the machinery to easily allow runtime addition/removal of bindings.
Seth Ladd's Polymer.dart examples are awesome and really helpful. The observable_list example appends DateTime instances to an ObservableList timestamps. Although DateTime does not extend Observable, modifying my_element.html to access a field on
{{ts in timestamps}}
works when running in the Dart VM. For example, changing
<li>{{ts}}</li>
to
<li>{{ts.second}}</li>
will access the DateTime.seconds field when on the Dart VM. However, when dart2js compiles the app to javascript, access to fields in the Polymer expression is broken. An exception Uncaught Error: RangeError: value 0 is thrown in this case, or more generally NoSuchMethodError : method not found: 'Symbol(...)' for the fieldname is thrown (see example here)
If a class extends Observable then access to #observable fields works inside of Polymer expressions after compiling to Javascript (changing the class MyRow in this example to extends Observable does not throw an exception in javascript).
What can I do when I am unable to add annotations to external classes like DateTime? Is this just a current bug in dart2js generation, or will the Polymer.dart spec forbid reading fields out of non-observable classes? Previously, web_ui successfully accessed fields from our dart-protobuf generated classes after compiling to javascript, so I'm hoping this use-case will gain support in Polymer.dart too.
In general, dart2js tries to tree-shake and minify code, and it doesn't know that some of the code is used from a polymer expression (which uses mirrors internally to interpret the expressions). Very likely what happened here is that dart2js is either deleting the non-observable fields or minifying them in a way that they are not reflectable.
To fix this, you can indicate that these fields need to be preserved and used via mirrors. In polymer we provide the #reflectable annotation for this purpose. (#observable also implies #reflectable, that's why it works when you have #observable). So you can use that in the MyRow case.
Fields from types in the core libraries can work also if they become reflectable. In this case it is a bit harder to express because you can't modify the original code to add this annotation. Instead you can use the #MirrorsUsed annotation to override the default behavior on these core types, or avoid using these fields inside polymer-expressions by hiding them inside #reflectable getters or in filters that are written directly in Dart code.
Is there a procedure to call an "init" method on a polymer element in Dart in order to populate it?
I have a polymer template (still not sure it's correct) and I want to populate it with the results of an HttpRequest. I can populate with a static list, but not sure how to populate it with a dynamic list made via an http call.
Are there examples anywhere?
I'm still trying to come up to speed on Dart and Polymer ...
My hacks are at https://gist.github.com/fils/6270699
Have you considered putting the init code inside a created() lifecycle method? You can see an example of that at https://github.com/dart-lang/web-ui/blob/polymer/example/todomvc/web/todo_row.dart