【问题标题】:Polymer dart: Data bind integer value to String attribute聚合物飞镖:数据将整数值绑定到字符串属性
【发布时间】:2014-09-01 19:05:25
【问题描述】:

我正在尝试将整数绑定到字符串属性。确切地说,我试图将发布的整数变量绑定到文本输入元素的 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}}">

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

【问题讨论】:

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


    【解决方案1】:

    对于 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}}">
    

    【讨论】:

      【解决方案2】:

      这适用于 聚合物 。对于 Polymer >= 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 表达式
      就像polymer dart input binding int properties中解释的那样

      替代方法e 使用 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>
      

      【讨论】:

        猜你喜欢
        • 2014-06-26
        • 1970-01-01
        • 2013-08-24
        • 1970-01-01
        • 2015-01-18
        • 1970-01-01
        • 1970-01-01
        • 2015-03-23
        • 2014-10-05
        相关资源
        最近更新 更多