Как я могу запустить пользовательское событие от Polymer Dart?

Я хочу запустить/отправить/исправить пользовательское событие изнутри элемента Polymer. Например, я хочу преобразовать нормальное событие DOM, например "изменено", в более семантическое событие типа "todoupdated".

Это HTML, который у меня есть:

<polymer-element name="todo-item" extends="li" attributes="item">
  <template>
    <style>
      label.done {
        color: gray;
        text-decoration: line-through;
      }
    </style>
    <label class="checkbox {{item.doneClass}}">
      <input type="checkbox" checked="{{item.done}}">
      {{item.text}}
    </label>
  </template>
  <script type="application/dart" src="todo_item.dart"></script>
</polymer-element>

Я хочу, чтобы события изменений на флажке выходили из пользовательского элемента как нечто более... полезное.:)

Ответ 1

Шаг 1

Захват событий изменений на <input>. Обратите внимание на on-change ниже.

<!-- from inside todo_item.html -->
<input type="checkbox" checked="{{item.done}}" on-change="{{change}}">

Шаг 2

Обработать событие изменения в коде пользовательского элемента, который содержит этот флажок.

import 'package:polymer/polymer.dart';
import 'dart:html';
import 'models.dart';

@CustomTag('todo-item')
class TodoItemElement extends PolymerElement with ObservableMixin {
  @observable Item item;

  bool get applyAuthorStyles => true;

  void change(Event e, var details, Node target) {
    // do stuff here
  }
}

Обратите внимание на обработчик события change. Этот метод запускается каждый раз при изменении состояния флажка.

Шаг 3

Отправка пользовательского события.

  void change(Event e, var details, Node target) {
    dispatchEvent(new CustomEvent('todochange'));
  }

ПРИМЕЧАНИЕ: имя настраиваемого события не должно содержать тире.

Шаг 4

Слушайте пользовательское событие в родительском настраиваемом элементе.

    <template repeat="{{item in items}}" >
      <li is="todo-item" class="{{item.doneClass}}" item="{{item}}" on-todochange="todoChanged"></li>
    </template>

Обратите внимание на использование on-todochange.

Наслаждайтесь!

Ответ 2

Полимер имеет вспомогательный метод, который упрощает события стрельбы

// dispatch a custom event
this.fire('polymer-select', detail: {'item': item, 'isSelected': isSelected});

Дополнительная информация:
Чтобы сделать событие доступным для подписчика, который хочет добавить слушателя программно

// getter
async.Stream<dom.CustomEvent> get onPolymerSelect =>
    PolymerSelection._onPolymerSelect.forTarget(this);

// private EventStreamProvider
static const dom.EventStreamProvider<dom.CustomEvent> _onPolymerSelect =
    const dom.EventStreamProvider<dom.CustomEvent>('polymer-select');

подписываться на событие программно, а не декларативно:

($['#ps'] as PolymerSelect) // get the children and cast it to its actual type
    .onPolymerSelect.listen((e) => print(e['isSelected'])); // subscribe

Ответ 3

Мне это удалось с помощью <core-signals> и метода полимерного помощника fire. Таким образом, вы можете слушать события, выпущенные из элементов, которые не являются дочерними. источник.

todochange.html

<!doctype html>

<polymer-element name="todo-item" extends="li">
  <template>
    <style>
      label.done {
        color: gray;
        text-decoration: line-through;
      }
    </style>
    <label class="checkbox {{item.doneClass}}">
      <input type="checkbox" checked="{{item.done}}">
      {{item.text}}
    </label>
  </template>
  <script type="application/dart" src="todo_item.dart"></script>
</polymer-element>

todochange.dart

import 'package:polymer/polymer.dart';
import 'dart:html';

@CustomTag('todo-item')
class TodoItemElement extends PolymerElement {
  @observable Item item;

  void change(Event e, var details, Node target) {
    // the name is the name of your custom event
    this.fire( "core-signal", detail: { "name": "todochange" } );
  }
}

Тогда любой абонент просто должен это сделать

subscriber.html

...
<link rel="import" href="packages/core_elements/core_signals.html>
...
<template>
  <core-signals on-core-signal-todochange="{{handleToDoChange}}"></core-signals>
...
</template>

subscriber.dart

@CustomTag( "subscriber" )
class Sub extends PolymerElement {
  ...
  void handleToDoChange( Event e, var detail, Node target ) {
    print( "Got event from <todo-item>" );
  }
  ...
}