Polymer dart:数据绑定整数值到String属性

时间:2014-09-01 19:05:25

标签: data-binding binding filter dart dart-polymer

我正在尝试将整数绑定到String属性。确切地说,我试图将已发布的整数变量绑定到文本输入元素的value属性。

@published int data = 0;

<input type="number" value="{{data}}">

显然,String的引用存储在应该是整数的内容中。

我尝试使用过滤器来解决这个问题,但仍然可以让它起作用:

int integerize(Object a) {
  int ret = 0;
  if (a is String) {
    try {
      ret = int.parse(a);
    } on FormatException catch (e) {
    }
  } else if( a is int) {
    ret = a;
  }
  return ret;
}

<input type="number" value="{{data | integerize}}">

所以我切换到不使用绑定。有人可以建议使用绑定更好,更有效的解决方案吗?

2 个答案:

答案 0 :(得分:2)

对于 Polymer 1.0.0 ,这对我来说很好用

创建可重用的行为或只将convertToNumeric()添加到Polymer元素:

@HtmlImport('app_element.html')
library app_element;
import 'dart:html' as dom;
import 'package:web_components/web_components.dart' show HtmlImport;
import 'package:polymer/polymer.dart';

@behavior
abstract class InputConverterBehavior implements PolymerBase {
  @reflectable
  void convertToInt(dom.Event e, _) {
    final input = (e.target as dom.NumberInputElement);
    double value = input.valueAsNumber;
    int intValue =
        value == value.isInfinite || value.isNaN ? null : value.toInt();
    notifyPath(input.attributes['notify-path'], intValue);
  }
}

将行为应用于您的元素:

@PolymerRegister('app-element')
class AppElement extends PolymerElement with InputConverterBehavior {
  AppElement.created() : super.created();

  @property int intValue;
}

在元素的HTML中配置输入元素:

  • value绑定到您的媒体资源:value="[[intValue]]",以便在媒体资源发生变化时更新输入元素
  • 设置事件通知,以便在值更改on-input="convertToNumeric" notify-path="intValue"时调用转换器,其中intValue是要使用数值更新的属性的名称。
<!DOCTYPE html>
<dom-module id='app-element'>
  <template>
    <style>
      input:invalid {
        border: 3px solid red;
      }
    </style>
    <input type="number" value="[[intValue]]"
           on-input="convertToInt" notify-path="intValue">

    <!-- a 2nd element just to demonstrate that 2-way-binding -->
    <input type="number" value="[[intValue]]"
           on-input="convertToInt" notify-path="intValue">
  </template>
</dom-module>

另一种方法

创建一个属性作为getter / setter:

  int _intValue;
  @property int get intValue => _intValue;
  @reflectable set intValue(value) => convertToInt(value, 'intValue');

创建行为或将函数直接添加到元素

@behavior
abstract class InputConverterBehavior implements PolymerBase {
  void convertToInt(value, String propertyPath) {
    int result;
    if (value == null) {
      result = null;
    } else if (value is String) {
      double doubleValue = double.parse(value, (_) => double.NAN);
      result =
          doubleValue == doubleValue.isNaN ? null : doubleValue.toInt();
    } else if (value is int) {
      result = value;
    } else if (value is double) {
      result =
          value == value.isInfinite || value.isNaN ? null : value.toInt();
    }
    set(propertyPath, result);
  }
}

这样,您可以使用与文本输入字段相同的标记

<input type="number" value="{{intValue::input}}">

或者如果要延迟更新属性,直到输入字段保留

<input type="number" value="{{intValue::change}}">

答案 1 :(得分:1)

这是针对 Polymer&lt; = 0.16 。对于 Polymer&gt; = 1.0 ,请参阅我的其他答案。

HTML属性仅存储字符串值。你可以做的是使用getter / setter进行绑定,并在设置值时解析。

@observable
int data;

@ComputedProperty('data') // haven't tried this but should work - see comments on http://japhr.blogspot.co.at/2014/08/whats-difference-between-attribute-and.html
@observable
get dataValue => data;
set dataValue(val) {
  if(val == null) {
    data = 0;
  } else if(val is num) {
    data = val.toInt();
  } else if(val is String) {
    data = num.parse(val, (v) => 0).toInt();
  } else {
    data = 0;
  }
}

或使用变压器或自定义聚合物表达式
polymer dart input binding int properties

中所述

替代方法 使用Dart Polymer 1.0(也可以使用Dart Polymer 0.16)

<强> app_element.dart

@HtmlImport('app_element.html')
library _template.web.app_element;

import 'dart:html' as dom;
import 'package:web_components/web_components.dart' show HtmlImport;
import 'package:polymer/polymer.dart';

@PolymerRegister('app-element')
class AppElement extends PolymerElement {
  AppElement.created() : super.created();

  @property int intValue;
  @property String stringValue;

  @reflectable
  valueInputHandler(dom.Event event, [_]) {
    var input = (event.target as dom.NumberInputElement);
    var value = input.valueAsNumber;
    if (!value.isNaN && !value.isInfinite) {
      set('intValue', value.toInt());
      input.setCustomValidity('');
    } else {
      // just to get the `:invalid` pseudo-class for styling
      input.setCustomValidity('Not a number.');
    }
  }
}

<强> app_element.html

<!DOCTYPE html>
<dom-module id='app-element'>
  <template>
    <style>
      input:invalid {
        border: 3px solid red;
      }
    </style>
    <input type="number"
           value="{{stringValue::input}}"
           on-input="valueInputHandler" >
    <div>stringValue: <span>{{stringValue}}</span></div>
    <div>intValue:<span>{{intValue}}</span></div>
  </template>
</dom-module>