How do I pass arbitrary data to a click event handler function from a Dart polymer web component
Asked Answered
M

3

19

In Dart's Web UI, it was possible to pass arbitrary data to function in response to events, for example, the following snippet passes the value 2 to the increment(int incBy) method in response to the button's on-click event:

<!-- Web UI -->
<element name="x-click-counter">
  <template>
    <button on-click="increment(2)">  <!-- passing a value of 2 -->
      Click me
    </button>   
  </template>
</element>
<script>
  import 'package:web_ui/web_ui.dart';

  class CounterComponent extends WebComponent {
    void increment(int incBy) {        // accept the value of 2
      count = count + incBy;
    }
  }
</script>

In Polymer (and Polymer.dart), the on-click event attribute requires a string version of the function name, rather than an actual function call. This is described on the polymer docs page as:

The value of an event handler attribute is the string name of a method on the component. Unlike traditional syntax, you cannot put executable code in the attribute.

Using polymer.dart, this looks like:

<polymer-element name="x-click-counter">
  <template>
    <button on-click="increment">  <!-- can't pass a value of 2, as you need to pass a string -->
      Click Me
    </button>
  </template>
</polymer-element>
<script>
  import 'package:polymer/polymer.dart';

  @CustomTag("x-click-counter")
  class CounterComponent extends PolymerElement with ObservableMixin {
    @observable int count = 0;

    void increment(Event event, var detail, var target) {  // How do I pass 2 to this function?
      count = count ++;
    }
  }
</script>

Question: How do I pass an arbitrary value to the increment function?

Mamba answered 15/8, 2013 at 8:39 Comment(0)
M
19

You can use html data- attributes to pass extra data, and then access them through the target parameter.

Re-writing the polymer example to add a data-incby field that takes the value increment the count by looks like this:

<polymer-element name="x-click-counter">
  <template>
    <button on-click="increment"  data-incby="2">  <!-- now passing the value as a data attribute -->
      Click Me
    </button>
  </template>
</polymer-element>
<script>
  import 'package:polymer/polymer.dart';

  @CustomTag("x-click-counter")
  class CounterComponent extends PolymerElement with ObservableMixin {
    @observable int count = 0;

    void increment(Event event, var detail, var target) {
      int incBy = int.parse(target.attributes['data-incby']);  // extract the value 2
      count = count + incBy;
    }
  }
</script>
Mamba answered 15/8, 2013 at 8:39 Comment(1)
@Cengiz It is considered inappropriate to make substantive changes to someone else's answer, even if it is completely wrong. Instead, please post a new answer with your changes.Sobranje
I
14

Dart and Polymer.dart have changed since Chris' answer. Here is updated code for Dart v1.0:

<polymer-element name="x-click-counter">
  <template>
    <button on-click="{{increment}}"  data-incby="2">  <!-- now passing the value as a data attribute -->
      Click Me
    </button>
    <span>{{count}}</span>
  </template>
</polymer-element>
<script type="application/dart">
  import 'package:polymer/polymer.dart';
  import 'dart:html';

  @CustomTag("x-click-counter")
  class CounterComponent extends PolymerElement {
    @observable int count = 0;

    CounterComponent.created() : super.created();

    void increment(Event event, var detail, var target) {
      int incBy = int.parse(target.attributes['data-incby']);  // extract the value 2
      count = count + incBy;
    }
  }
</script>
Icarus answered 13/12, 2013 at 22:15 Comment(2)
for 'data-xxx' attributes target.dataset may be a better option than target.attributesGreenlee
I love how in React JSX, you can just write function calls in JS, instead of doing workarounds like this.Ensemble
K
1

My solution for Polymer 0.11.0+5

element.html

<link rel="import" href="../packages/polymer/polymer.html">
<polymer-element name="dp-element">
  <template>
    <div class="row">
    <ul>
      <template repeat="{{ item in items }}">
        <li on-click="{{load}}" data-incby="{{item}}">{{ item }}</li>
      </template>
    </ul>

  </template>

 <script type="application/dart">
  import 'package:polymer/polymer.dart';
  import 'view.dart';
  import 'dart:html';

  @CustomTag('dp-element')
  class DpElement extends PolymerElement {

  @observable List<String> items;

  DpElement.created() : super.created(){
  }
  void load(Event event, var detail, var target) {
     String incBy = target.attributes['data-incby'];
     print(incBy);
  }
}
Keeler answered 11/7, 2014 at 14:3 Comment(1)
You can also take a look at my answer to this question stackoverflow.com/questions/24530054. Polymer implicitely assigns item to <li> My answer to the linked question shows just how to acquire that value.Greenlee

© 2022 - 2024 — McMap. All rights reserved.