Victor Ermolaev
Victor Ermolaev

Reputation: 791

Dart Polymer: How to set a non-string field in custom at creation

I am writing a polymer app. I extend a polymer element as follows:

@CustomTag("custom-element")
class CustomElement extends PolymerElement {
  @published List<String> years;      
  CustomElement.created() : super.created();
}

the corresponding html:

<link rel="import" href="../../../../packages/polymer/polymer.html">
<polymer-element name="custom-element" attributes="years">
  <template>
    Years listed are 
    <template repeat="{{ year in years }}">
      <p> {{ year }} </p>
    </template>    
  </template>
  <script type="application/dart" src="custom_element.dart"></script>
</polymer-element>

and in a dart script referenced in the entry html file, after I have fetched some data from server I dynamically create such elements:

initPolymer().run((){
  querySelect("#custom-elements").children.add(
    new Element.tag("custom-element")
    ..id = "my_custom_element"
  );
});

Given code works fine if years in CustomElement is set to some value, now I want to set it in my main script. If the property years was of type String then I would simply altered the last piece to

initPolymer().run((){
  querySelect("#custom-elements").children.add(
    new Element.tag("custom-element")
    ..id = "my_custom_element"
    ..setAttribute("years", "2010")
  );
});

But the problem is that I need to set a whole List, not a single value. I can't figure out a way to do so. How would I go about this? Solutions and suggestions are very welcome.

EDIT: So my main script looks as follow

void main(){
  // in reality this list is fetched from the server
  List<String> customYears = ['2010', '2011'];

  initPolymer().run((){
    querySelect("#custom-elements").children.add(
      new Element.tag("custom-element")
      ..id = "my_custom_element"
      // HERE I would like to set a public field *years*
      // of the CustomElement

      // the following does not work

      // 1.
      // ..setAttribute('years', customYears) 
      // Exception: Uncaught Error: type 'List' is not a subtype of type 'String' of 'value'.

      // 2.
      // ..setAttribute('years', toObservale(customYears)) 
      // Exception: Uncaught Error: type 'ObservableList' is not a subtype of type 'String' of 'value'.

      // 3.
      // ..years = customYears
      // ..years = toObservable( custom Years )
      // NoSuchMethodError: method not found: 'years='
    );
  });
}

So the question is, how do I assign a value to a non-string member field of an instance of CustomElement outside the class itself? A straightforward assignment inside the class causes no problems, but this isn't what I seek for. I hope I explained myself more clearly now.

Upvotes: 1

Views: 130

Answers (2)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 658205

Basically @Ozan answers your actual question but there is an additional issue. The element is not yet fully initialized when the code assigns the value. This is the reason Dart fails and tells you that HtmlElement doesn't have a setter years. After adding Polymer.onReady.then() Polymer is fully initialized and the assignment works.

Hint: If you cast the created element to its concrete type you don't get a warning in DartEditor.

import 'package:polymer/polymer.dart';
import 'dart:html';
// added import to be able to use the type
import 'custom_element.dart'; 

void main() {
  // in reality this list is fetched from the server
  List<String> customYears = ['2010', '2011'];

  // Polymer => 0.16.0
  initPolymer().then((zone) => zone.run(() {
    Polymer.onReady.then((_) { // added - wait for onReady
      querySelector("#custom-elements").children.add(
          (new Element.tag('custom-element') as CustomElement)
            ..id = "my_custom_element"
            ..years = toObservable(customYears));
    });
  }));
}

it is more convenient to add a constructor to the custom element like

import 'package:polymer/polymer.dart';
import 'dart:html';

@CustomTag('custom-element')

class CustomElement extends PolymerElement {

  factory CustomElement() {
    final x =  new Element.tag('custom-element');
    return x;
  }

  CustomElement.created() : super.created();

  @published List<String> years;
}

then you can create the element like

 querySelector("#custom-elements").children.add(
          new AppElement()
            ..id = "my_custom_element"
            ..years = toObservable(customYears));

see also

Upvotes: 2

Ozan
Ozan

Reputation: 4415

Try to simply assign the value to the field:

import 'package:observe/observe.dart';

initPolymer().run((){
  querySelect("#custom-elements").children.add(
    new Element.tag("custom-element")
    ..id = "my_custom_element"
    ..years = toObservable(["2010"])
  );
});

Usually custom elements are used in a main polymer element and attributes like years are bound to its scope:

<link rel="import" href="../../../../packages/polymer/polymer.html">
<polymer-element name="main-element">
  <template>
    <custom-element years="{{years}}"></custom-element>
  </template>
  <script type="application/dart" src="main_element.dart"></script>
</polymer-element>
@CustomTag("main-element")
class MainElement extends PolymerElement {
  @published List<String> years = toObservable(["2010"]);      
  MainElement.created() : super.created();
}

Upvotes: 1

Related Questions