【问题标题】:Dynamically bind (or format) two @observable variables to a third @observable variable将两个@observable 变量动态绑定(或格式化)到第三个@observable 变量
【发布时间】:2014-06-11 05:26:39
【问题描述】:

这是我认为可能更容易一些的事情。尽管问题很具体,但我对任何可以让我根据 Polymer.dart 的其他两个字段的内容自动更新第三个表单字段的方法感兴趣。

类似这样,其中“[ ]”表示表单字段。

姓名:[名字] [姓氏]

全名:[family_name, given_name]

例如;如果有人在前两个字段中输入“John”和“Smith”。然后“全名”行显示:[Smith, John],当任一字段更新时。

以下示例基于 Dart Polymer 教程中的类和标记

对于这样的表格...

  <polymer-element name="reference-form" extends="form" >
    <template>
      <style> ... </style>
      <div id="slambookform"  >
        <div class="entry">
          <label>Author:</label>
          <input type="text" value="{{theData['authorGivenName']}}" >
          <input type="text" value="{{theData['authorFamilyName']}}">
        </div>
          :
        <div class="entry">
          <label>Full name:</label>
          <input disabled type="text" value="{{fullName}}" >
        </div>
          :
      </div>
    <template>
  </polymer-element>

我最初的尝试是这样的函数:

@observable
String fullName(){

    return theData['authorFamilyName'] +', '+ theData['authorGivenName'];

}

这不起作用。当我将'fullName'设置为@observable 变量并使用按钮更新它时,表单会根据需要进行更新。因此我的问题是,我可以将第三个字段绑定到两个(或更多)其他字段吗?

我想我需要某种事件处理程序。对于两个字段,对更改进行格式化甚至非常简单。我想在最终情况下格式化几个字段,而不仅仅是两个字段。

在这个主题上,dart-polymer 或 dart 中是否有一个钩子来提供未来或回调?在我的示例中,类似于:'after-change'。只是大声思考,这样的事情会很好。

提前致谢。

【问题讨论】:

标签: dart dart-polymer


【解决方案1】:

按照这些思路(注意 - 代码未经测试)

 <polymer-element name="reference-form" extends="form" >
    <template>
      <style> ... </style>
      <div id="slambookform"  >
        <div class="entry">
          <label>Author:</label>
          <input type="text" value="{{authorGivenName}}" >
          <input type="text" value="{{authorFamilyName}}">
        </div>
          :
        <div class="entry">
          <label>Full name:</label>
          <input disabled type="text" value="{{fullName}}" >
        </div>
          :
      </div>
    <template>
  </polymer-element>

类reference_form.dart

String _authorGivenName;
@observable get authorGivenName => _authorGivenName;
set authorGivenName(String val) {
  _authorGivenName = val; 
  notifyPropertyChange(#fullName, '${_authorGivenName} ${_authorFamilyName}', 
    '${val} ${_authorFamilyName}');
}

String _authorFamilyName;
@observable get authorFamilyName => _authorFamilyName;
set authorFamilyName(String val) {
  _authorFamilyName = val; 
  notifyPropertyChange(#fullName, '${_authorGivenName} ${_authorFamilyName}',
    '${_autorGivenName} ${val}');
}

@observable
String get fullName => '${_authorGivenName} ${_authorFamilyName}';

【讨论】:

  • 感谢君特的指点;发布的示例不太有效。我在下面发布了一个最小版本,以展示我如何进行更改以演示 概念证明
  • 我明白了,这里使用notifyPropertyChange的返回值是不合适的。评论中的“谢谢”很好,但在 StackOverflow 中通常首选赞成票。
  • 完成。我尽可能避开政治。
  • 你在 StackOverflow 上有聊天室吗?用闲聊来搅乱 QnA 空间似乎并不合适。
  • 我刚刚创建了一个名为Dart
【解决方案2】:

我有一个解决这个问题的方法,站在 Günter Zöchbauer 的肩膀上(上面的评论)。我的目标是以只读方式将一个字段值“绑定”到两个。我们还没有完全做到这一点,但是这条途径本身就是教育性的。

观察者法

这个解决方案是我为自己设定的目标的一种解决方法。我在这段代码上做了一些注释来解释我看到了什么,或者我认为为什么会发生。

目的是让 fullName 以如下形式显示两个名称:

  • 家庭名称,给定名称;例如
  • 史密斯,约翰

参考表格.html:

<polymer-element name="reference-form" extends="form" >
    <template>
      <style> ... </style>
      <div id="slambookform"  >
        <div class="entry">
          <label>Author:</label>
          <input type="text" value="{{theData['givenName']}}" >
          <input type="text" value="{{familyName}}">
        </div>
          :
        <div class="entry">
          <label>Full name:</label>
          <input disabled type="text" value="{{fullName}}" >
        </div>
          :
      </div>
    <template>
  </polymer-element>                                          

表单属性的代码,Polymer-dart 使用小胡子语法“{{fullName}}”绑定到 HTML 的东西。为了简单起见,我只使用了一个 'notifier' 字段,这会更新 familyNamegivenName 中的 fullName 字段em>。

reference_form.dart:

  //---- testing ----

  String _familyName;                        // (1) 
  @observable                                // (2)
  String get familyName => _familyName;      // (3)
  void   set familyName( String nam ){       // (4)
      _familyName = nam; 
      fullName    = notifyPropertyChange(    // (5)
                        #fullName, 
                        "${fullName}", 
                        "${nam}, ${theData['givenName']}" );
  }

  @observable
  String fullName;                           // (6)

  //---- end: testing ----

私有成员“_familyName”是模板中使用的公共 familyName 属性的影子(上面的 sn-p)。

  1. 影子(私有)成员“_familyName”存储 familyName 伪属性的数据。
  2. 接下来的三行声明了一个@observable 属性,familyName
  3. Get familyName。只需回显阴影变量的值即可。
  4. SetfamilyName。更新阴影变量和复合 fullName 属性。
    • 注意:合成格式可以完成两行:
      _familyName = nam;
      全名 = 南;
      ...但我们希望看到传播的所有更改,请参阅 (#5)。
  5. notifyPropertyChange() 方法更新了 fullName 属性的所有 个观察者。
    • 注意:我并没有在 Polymer 内部乱搞;在 Observable 类中,fullName 没有显示代码的观察者。
    • 在我看到这个之前,我认为 Polymer 绑定到 HTML 模板是通过观察者(观察者)进行的,但似乎不是。我可能弄错了。在任何情况下,对“#fullName”符号的 notifyPropertyChange() 调用都不会更改此测试用例的结果。
  6. fullName 属性绑定到 Polymer 表单。

基本上,每次 familyName 发生更改时,{{fullName}} 值都会更新伪属性。

效率说明

  • 每次击键都会调用familyName 设置器(在调试时观察)。我理解这一点,并认为这并不总是最好的解决方案。
  • 对我来说,我宁愿只在用户退出该字段时调用 setter。然而,当我使用 onblur 时,触发器是表单的模糊,而不是字段。
  • 似乎我们都可以在性能方面受益,获得更多关于这些钩子、路径和任何可用选项的内部信息,以提高效率。

欢迎提出意见和改进。这个例子对我来说是一个解决方法,所以它绝对是一个正在进行的工作。 ;-)

封装方式

我正在根据上面的“观察者方法”开发一个更接近最初目标的解决方案。这种方法依赖于当前(即 Dart v4)对模块和库的使用。我会先展示工作代码,然后用注释解释有趣的东西。

reference_form.dart:

import 'package:exportable/exportable.dart';                // [1]

class _Data                                                 // [2]
    extends Object with Exportable {                        // [3]

    @export String publishDate;                             // [4]
    @export String authorGivenName  = '(given)';
    @export String authorFamilyName = '(family)';
    @export String authorUrl        = ''; 

        //--- attributes ---

    String get fullName => "${authorFamilyName}, ${authorGivenName}"; // [5]
    void   set fullName( String nam ){                                // [6]
        //don't need this
    }

        //--- ctor ---

    _Data(){
        publishDate  = new DateTime.now().toString();                 // [7]
    }

} //_Data


@CustomTag('reference-form')
class SlamBookComponent extends FormElement with Polymer, Observable {

  SlamBookComponent.created() : super.created();

  //---- testing ----

  @observable
  _Data data = new _Data();                                           // [8]

      :

} //SlambookComponent      

注意事项

  1. 包含 Exportable mixin 以转换为 JSON。我没有导出“fullName”,因为它目前只是在格式化。
    • exportable 添加到您的 pubspec.yaml 和“Run Pub get”。
  2. “_Data”类是 reference_form.dart 模块私有的。我对范围规则做了一些测试,因为我不希望内部数据结构泄漏,当然除了像 JSON 这样的天主教(small-c)。
  3. 引入 Exportable 混合。
    • 我已经测试了Exportable,它完全实现了我认为我必须自己编写的内容。对此感到满意。
    • JSON 不是原始问题的要求;但我确实希望 (eventual) 解决方案成为可序列化或保存的一流人工制品,这在我的大多数用例中都很重要。
    • 这是快速灵活地扩展 Dart 工具的一个很好的例子!
  4. 使用 @export 修饰符来识别特定字段,以交换为 JSON。
  5. fullName 属性导出为 String (get)。
  6. 不需要设置操作。然而 Dart 显然坚持 Set 方法匹配 'get'。
    • 我对此感到失望。我更喜欢我可以拥有只读属性和属性的想法,例如喜欢
    • 经测试,Dart SDK v1.4.0;当匹配的 setter 未实现/声明时失败(??)。
  7. 使用构造函数设置日期数据属性的初始值。
  8. 将名为“data”的不透明公共属性声明为 (private) _Data 实例。
    • 关键字段的数据格式封装在私有_Data声明中。
    • Exportable mixin 接口用于将私有类映射到 public JSON 结果。

#8 点展示了 的强大方面,以启用对象的不透明实现,然而,您可以'deliver'/'share 没有具体内部细节的细节。

我已运行此代码并检查了这些概念是否适用于隐藏数据(_Data 类型)以及不透明的访问和序列化。此外,您不能意外查看内部私有类型(意外,尽管可能会出现显式黑客攻击)。我不会为接受 C/C++ 有意识的责任范式而道歉——我认为这是作为程序员最强大的方面; 我们对我们生成的代码产生的影响/错误负责。我建议在小型迷你用例中测试“bits 行为”。

我放了 标记的例子;没什么奇怪的。对我来说,这种方法比原始(早期)Dart 教程更简洁,更面向对象

reference_form.html

  <polymer-element name="reference-form" extends="form" >
    <template>
    <style> ... </style>
      <div id="slambookform"  >

        <div class="entry">
          <label>Author:</label>
          <input type="text" value="{{data.authorGivenName}}" >
          <input type="text" value="{{data.authorFamilyName}}">
        </div>
        <div class="entry">
          <label>Published:</label>
          <input type="date" value="{{data.publishDate}}">  
        </div>

      </div>
    </template>

    <script type="application/dart" src="reference_form.dart"> </script>
  </polymer-element>

Polymer 标记中可以知道(并且具有可见性)内部字段名称。 为什么?

... 因为“reference_form.html”和“reference_form.dart”通过 Polymer-dart。真的很不错;尽管“.dart”和“.html”组件似乎像 ASP.NET 和 C#/VN.NET 一样紧密耦合,因为(也)为方便指定(??)。我承认这是一个完全不同的主题。有事情要解决,要保留事情yar(游艇术语)。

无论如何,对我来说,我觉得从上面的封装混乱开始的方法更适合我对小型实用程序的需求。


【讨论】:

  • 你可以为你创建一个关于模糊问题的问题吗?
  • 我不同意使用 *notifyPropertyChange*() 返回的评论。恕我直言,需要确保 fullName 属性被赋予与任何下游依赖观察者相同的值。这是一个数据完整性问题。在 Ruby、Smalltalk 和 MCS-s 等线程代码和消息传递系统中,当上游元素假设传递的数据与结果相同时,就会发生错误。在消息环境中,您绝不能假设。它是 MVC 等“消息系统”(MCS) 的热门列表项。那就是说;是的,你可以在像这个用例这样的小应用程序上用它作弊
  • 好的,但是在我的代码中,返回值被分配给了错误的字段。这是更改通知字段的值,而不是当前设置器的支持字段的值。
  • @Günter ... 支持字段评论。我调试了那个;它不适用于 Dart v1.4。我添加了更明确、更详细的 setter 语法来解开任何 Dart 内容,但它不起作用。那时我去了上面显示的Dart tips - Getters/Setters。无论如何,上面的答案只是一个原型。我肯定想找到一种绑定元素的方法,因为我想以不同的方式混合许多字段。
【解决方案3】:

Polymer 现在通过 @ObserveProperty 直接支持此用例

  @observable String authorGivenName = '';
  @observable String authorFamilyName = '';
  @observable String get fullName => '${authorGivenName} ${authorFamilyName}';

  @ObserveProperty('authorGivenName authorFamilyName')
  void updateFullName(old) {
    notifyPropertyChange(#fullName, old, fullName);
  }

【讨论】:

    猜你喜欢
    • 2019-06-27
    • 1970-01-01
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 2017-12-28
    • 1970-01-01
    • 2012-12-09
    相关资源
    最近更新 更多