Dart Polymer:如何在创建时自定义设置非字符串字段

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

我正在编写一个聚合物应用程序。我扩展一个聚合物元素如下:

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

对应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>

并且在条目 html 文件中引用的 dart 脚本中,在我从服务器获取一些数据 之后,我动态创建了这样的元素:

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

如果 CustomElement 中的 years 设置为某个值,给定的代码工作正常,现在我想在我的主脚本中设置它。如果 属性 yearsString 类型,那么我只需将最后一块更改为

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

但问题是我需要设置一个整体List,而不是单个值。我想不出这样做的方法。我该怎么做?非常欢迎解决方案和建议。

编辑: 所以我的主要脚本如下所示

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='
    );
  });
}

所以问题是,如何为 class 本身之外的 CustomElement 实例的 非字符串 成员字段赋值? class 中的直接赋值不会产生任何问题,但这不是我想要的。我希望我现在解释得更清楚了。

尝试简单地将值分配给字段:

import 'package:observe/observe.dart';

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

通常在主聚合物元素中使用自定义元素,并且年份等属性绑定到其范围:

<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();
}

@Ozan 基本上回答了您的实际问题,但还有一个问题。 当代码分配值时,该元素尚未完全初始化。这就是 Dart 失败并告诉您 HtmlElement 没有 setter 年的原因。添加后 Polymer.onReady.then() Polymer 已完全初始化并且分配有效。

提示:如果将创建的元素转换为其具体类型,则不会在 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));
    });
  }));
}

这样给自定义元素添加构造函数更方便
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;
}

然后你可以创建像

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

另见

  • Instantiating polymer element via dart code
  • how to implement a main function in polymer apps