Question

Code for a very small app illustrating these multiple constructor calls is now up on GitHub at https://github.com/Chiba-City/testnest.

I am trying to figure out

  1. why a polymer element would be constructed twice and
  2. what determines the order of construction of polymer elements that contain other polymer elements and
  3. why is a "templated out" element using an "if" template constructed at all.

Also, if one cannot reproduce these results with three simple polymer elements, one defined to contain or nest the other two, I would also love to know that as well.

I am finding duplicate constructor calls and constructor ordering peculiarities. Here is an explanation of the occurrence of these peculiarities.

I have a very simple "app". There is an index.html file that html-includes a file of custom element definitions and declares just one custom polymer-dart element in its body. Here are the relevant portions of the index.html file. I have elided the customary boiler plate.

<!-- index.html -->
<!-- in head -->
<link rel="import" href="icapp.html">
<!-- boiler plate polymer/init.dart and ../dart.js stuff here -->

<!-- only contents of body tag -->
<icount-app></icount-app>

Now in "icapp.html" I define two elements consisting only of h3 labels. I contain these two elements in the template for a third element which begins with a simple H1 label. Here is the code for all three elements.

<!-- icapp.html -->
<!-- User stats list -->
<polymer-element name="icount-statlist" >
  <template><h3>My Stats</h3></template>
</polymer-element>

<!-- Find stats -->
<polymer-element name="icount-findstats" >
  <template><h3>Find New Stats</h3></template>
</polymer-element>

<!-- This is the element that contains the other two elements in its template -->
<polymer-element name="icount-app"> 
<template>
  <h1>icount.us</h1> <!-- a simple h1 heading -->

  <!-- Included always -->
  <icount-findstats></icount-findstats>

  <!-- Included conditionally - but can never be true -->
  <template if="{{false}}">
    <icount-statlist ></icount-statlist>
  </template>
<!-- End icount-app template -->
</template>
<!-- The code with the element definitions -->
<script type="application/dart" src="icapp.dart"></script>
</polymer-element>

I have put "print" statements in the ".created() : super.created" constructors as well as overriden "enteredView()" methods to determine the order and frequency of these calls. Here is the output during execution. I have added notes prefixed with "--"

-- note this is first, although conditional on {{false}}
IcountStatlist: created           
-- now the containing element is constructed
IcountApp: created                
-- notice that enteredView happens before the nested element
IcountApp: enteredView
-- notice that this element is constructed twice
IcountFindstats: created          
IcountFindstats: created
IcountFindstats: enteredView

The output of the application is as expected (H1 and an H3 tags, the latter for the non-conditionally included "icount-findstats" element). But how it arrives here is peculiar, and in ways that would seem to defy adding reasonable program logic to these tags (properties, event handlers and so on).

  1. The visible nested element is constructed twice
  2. The "templated out" nested element is constructed once
  3. The visible nested element's "enteredView" method is called (not surprisingly).

Above the contained visible element is constructed after the containing element. But simple experimentation shows that this ordering seems arbitrary, or at least, not dependent on templating or ordering of nested elements.

If we simply switch our preference for which nested element we "template out" we get the following output instead.

IcountStatlist: created
IcountStatlist: created
IcountStatlist: enteredView
IcountApp: created
IcountApp: enteredView
IcountFindstats: created

Here we can note:

  1. The visible nested element, this time icount-statlist, is constructed twice, as above, but created before the containing element. Also the HTML output h3 tag occurs only once.

  2. This visible nested element's "enteredView" method is called prior to the containing element.

  3. The "templated out" nested element is again created (just once), but now after the containing element.

Further experimentation shows that the same element non-conditionally, visibly nested twice results in 4 constructor calls (for that element).

Another experiment shows that the same element conditionally contained twice results in 2 constructor calls (for that element).

Experimenting with reordering the "templated out" element and the visible element reveals no change in log output, i.e., the order or frequency of constructor calls.

Needless to say, I am perplexed.

  • Why is the visible nested element constructed twice ?

  • Why is the "templated out" nested element constructed at all ?

  • Why is one nested element constructed before the containing element and the other after ?

  • Why is the containing element, icount-app, itself not constructed twice?

  • How can a containing element sensibly set properties of contained elements given nature and ordering of custom polymer element (object) construction?

Any help greatly appreciated.

Was it helpful?

Solution

NOTE

  • enteredView was changed to attached
  • leftView to detached

-------

I tried your code and I can't reproduce the things you mentioned.

This is the output I got when I run your app:

nest-a: created
nest-a: enterView
nest-container: created
nest-container: enteredView
nest-b: created
nest-b: enteredView
  • the nested nest-b is not instantiated at all (the output is from the nest-b outside the <template if="{{false}}">

after changing false to true I get

nest-a: created
nest-a: enterView
nest-container: created
nest-container: enteredView
nest-b: created
nest-b: enteredView
nest-b: created
nest-b: enteredView

You need to put the value in quotes ="{{false}}" instead of ={{false}} It worked as expected anyway because this was evaluated to false as well but would fail for all other values/expressions

  • I don't know if the construction order is settled. Recently there was still a discussion whether it should be constucted inside out or document order. If you use binding this normally isn't an issue

Can you please post the output you got from the app you published to the GitHub repo?

OTHER TIPS

This problem occurred in the following stable release of Dart Editor.

$ dart --version 
Dart VM version: 1.2.0 (Tue Feb 25 07:34:09 2014) on "linux_x64"

Installation of the latest dev channel build of Dart SDK made the multiple constructor calls go away.

$ dart --version
Dart VM version: 1.3.0-dev.6.1 (Sat Mar 22 02:14:22 2014) on "linux_x64"

The output of the testnest project is now:

nest-a: created
nest-a: enterView
nest-container: created
nest-container: enteredView
nest-b: created
nest-b: enteredView

How to code around the order of nested element construction - both before and after the containing element - in Dart code remains an open exercise for the reader :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top