2

Here is a problem that cropped up today when I updated to the latest Dart libs.

The child custom element is a combo box. The parent custom element fills it with a varying list of strings.

// child HTML
<polymer-element name="bx-icombo" attributes="aLabel aList aSelected">
  <template>
    <div class='outr' flex layout horizontal center>
      <label for='inp' flex end-justified>{{aLabel}}</label>
      <!-- wait until the data is available -->
      <template if='{{aList}}'>
        <paper-dropdown-menu id='inp' label='aLabel' valign='top' flex start-justified >
          <paper-dropdown class="dropdown">
            <core-menu id='m' class="menu" selected="{{aSelected}}">
              <template repeat='{{aList}}'>
                <paper-item name='{{}}'>{{}}</paper-item>
              </template>
            </core-menu>
          </paper-dropdown>
        </paper-dropdown-menu>
      </template>
    </div>
  </template>

  <script type='application/dart' src='bx_icombo.dart'></script>
</polymer-element>

//---------------------------------------------------------------
// child Dart
@CustomTag('bx-icombo')
class BxICombo extends PolymerElement {

  @PublishedProperty(reflect: true)  String       aLabel;
  @PublishedProperty(reflect: true)  List<String> aList;
  @PublishedProperty(reflect: true)  String       aSelected;

  BxICombo.created() : super.created();
  }

//---------------------------------------------------------------
// Parent HTML
<polymer-element name="tst-sigs">
  <template>
    <paper-dialog backdrop heading='Sigs' closeSelector=''>
      <bx-icombo aLabel='{{selectAsignal}}'
                 aList='{{sigsList}}'
                 aSelected='{{sigsSel}}'>
      </bx-icombo>
    </paper-dialog>
  </template>

  <script type='application/dart' src='tst_sigs.dart'></script>
</polymer-element>

//---------------------------------------------------------------
// Parent Dart
@CustomTag('tst-sigs')
class TstSigs extends PolymerElement {

  @observable List<String> sigsList = ['alpha', 'beta', 'gamma'];
  @observable String sigsSel;
  @observable String selectAsignal = 'Select a Signal';

  TstSigs.created() : super.created();
  }

//---------------------------------------------------------------

Dartium reports:

Attributes on bx-icombo were data bound prior to Polymer upgrading the element. This may result in incorrect binding types. (:1)

So what has to be changed? @PublishedProperty or @observable or @published or .... I admit to finding the maze of @... annotations deeply unclear.

The versions are:

Dart: 1.9.3 (STABLE)
Dartium: 39.0.2171.99

and packages:

analyzer 0.24.6 (0.25.0+1 available)
args 0.12.2+6 (0.13.0 available)
barback 0.15.2+4
browser 0.10.0+2
cli_util 0.0.1+1
code_transformers 0.2.8
collection 1.1.0
core_elements 0.7.1+2
csslib 0.12.0
dart_style 0.1.8
glob 1.0.4
html 0.12.1+1
ini 1.1.0
initialize 0.6.0+4
intl 0.12.2
js 0.3.0
logging 0.9.3 (0.10.0 available)
markdown 0.7.1+2
matcher 0.11.4+4 (0.12.0-alpha.0 available)
observe 0.13.0+2
paper_elements 0.7.1
path 1.3.5
petitparser 1.3.7
polymer 0.16.1+4
polymer_expressions 0.13.1
polymer_interop 0.1.0+2
pool 1.0.1
quiver 0.21.3
smoke 0.3.2
source_maps 0.10.0+2
source_span 1.1.2
stack_trace 1.3.1
string_scanner 0.1.3+1
template_binding 0.14.0+2
utf 0.9.0+2
watcher 0.9.5
web_components 0.11.2
when 0.2.0
which 0.1.3
yaml 2.1.2

Initially a problem with code-transformers forced code_transformers < 0.2.5 and that limited polymer to 0.16.0. It looks as if the code transformer thing has been resolved so I have removed the version constraint and polymer updated to 0.16.1. The problem remains.

The main function is

import  'package:polymer/polymer.dart';
import  'lib/bxglobs/bxGlobs.dart' as G;

void realMain() {
  // empty for this test
}

void main() {

  G.initGlobals();

  initPolymer().then((zone) => zone.run(() {
    Polymer.onReady.then((_) => realMain());
  }));
}

and pubspec.yaml:

name: bxPoly
description: BX GUI
dependencies:
  core_elements: any
  ini: any
  intl: any
  js: any
  markdown: any
  paper_elements: any
  polymer: any
  code_transformers: any
transformers:
- polymer:
    entry_points:
    - web/test.html
timecc
  • 161
  • 1
  • 11

3 Answers3

1

This error almost always occurs because of elements getting registered in the wrong order. Specifically, a parent element being registered before a child element.

This is hard to diagnose without full access to the code, but following these two rules should ensure its not an issue:

  • Put each polymer-element in its own html file, and each class in its own dart library (using parts especially causes issues).
  • Make sure your elements import all of their dependencies.
Jake MacDonald
  • 1,348
  • 6
  • 7
  • How do I get a diagnostic dump of the order in which elements are being registered? Doesn't Dart enforce the import of all dependencies? If a custom element is descended from a base class do I need to import the dependencies of the base class (the editor will mark the extra imports as unused)? – timecc Apr 24 '15 at 17:44
0

edit

  <template if='{{aList != null}}'>
    <paper-dropdown-menu id='inp' label='aLabel' valign='top' flex start-justified >
      <paper-dropdown class="dropdown">
        <core-menu id='m' class="menu" selected="{{aSelected}}">
          <template repeat='{{a in aList}}'>
            <paper-item name='{{a}}'>{{a}}</paper-item>
          </template>
        </core-menu>
      </paper-dropdown>
    </paper-dropdown-menu>

original

  • If you bind from the shadow DOM of an element to its class @observable is enough.
  • If you want to bind to attributes from outside of an element use @published.
  • If you want to use the value of a bound attribute for example in CSS selectors use @PublishedAttribute(reflect: true). reflect means the properties value is reflected to the DOM, otherwise it's only available for Polymer and Dart code.

I haven't seen this error message before. Maybe there is a problem with Polymer initialization. Do you have a custom main? Can you add it to your question?

class MyA extends PolymerElement {
  @observable 
  aobservable = 'obs';

  @published 
  apublished = 'pub';

  @PublishedAttribute(reflect: true)
  areflected = 'ref';
}
<polymer-element name="my-a">
  <template>
    <!-- doesn't work
    <my-b bobservable="{{aobservable}}"></my-b> -->

    <my-b bpublished="{{aobservable}}"></my-b>
    <my-b breflected="{{aobservable}}"></my-b>
    <!-- you can bind properties of MyA here no matter if 
         they are observable/published/reflected
         (even when they have no annotation but they will not
         be updated when the value changes) 

         You can bind only to published (reflected or not)
         attributes of MyB
    -->
  </template>
</polymer-element>

class MyB extends PolymerElement {
  @observable 
  bobservable = 'obs';

  @published 
  bpublished = 'pub';

  @PublishedAttribute(reflect: true)
  breflected = 'rep';
}
<polymer-element name="my-b">
  <template>
  </template>
</polymer-element>
<head>
  <style>
    // you can only address reflected attributes here
    my-a[areflected="ref"] {
      backgroundColor: red;
    }
  </style>
</head>
<body>
 <my-a></my-a>
</body>
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thanks for the reply, but it still isn't clear. `@observable` is enough on the child, the parent, both? And if on only one, what goes on the other? Similarly for `@published` and `@PublishedAttribute(reflectOnTheMeaningOfLife:true)` :) The documentation is full of "it" and "this" where the meaning is known only to the author. I will make the example more complete. Is there any way to tell if Polymer initialization has completed successfully? – timecc Apr 24 '15 at 11:09
  • Apologies for the brief and useless comment. SO posted the comment when I pressed return. When I edited the comment to make it useful SO said that too much time had passed. – timecc Apr 24 '15 at 11:12
  • I see. Your comment really seemed quite pointless :D. I updated my answer. If you add a `ready()` method in your element, Polymer will call it when initialization of the element is completed. If you want to use your own main method see http://stackoverflow.com/a/20982658/217408. I discourage using a custom `main` because it often confuses users. If you have to, maybe because you also use Angular.dart, then check out my linked answer. – Günter Zöchbauer Apr 24 '15 at 11:36
0

This seems to be the solution. Based on debugging rather than knowledge, so beware..

Say your component foo.dart and foo.html refers to another component bar.dart and bar.html. For instance, the reference might be:

barEl el = document.querySelector('bar');

Obviously you import bar.dart at the top of foo.dart. You get the error described unless you also

<link rel="import" href="bar.html">

at the top of foo.html. Even though bar.html is not conventionally referenced in foo.html.

timecc
  • 161
  • 1
  • 11