2

I have a JavaScript class that has some events and I need to rewrite it to Dart. I dont know how to rewrite part where we use callbacks. This is my example code:

var Person = function (name) {
  this.name = name;
  this.onNameChangedCallbacks = [];
}

Person.prototype.onNameChanged = function(callback) {
  this.onNameChangedCallbacks.push(callback);
}

Person.prototype.setName = function (name) {
  this.name = name;
  this.onNameChangedCallbacks.forEach(function (callback){
    callback(name);
  });
}

var adam = new Person('Adam');

adam.onNameChanged(function(newName) {
  alert('New name is set to: ' + newName);
});

adam.setName('eva');

http://jsfiddle.net/R79Vy/

As you can see whe anytime when name is changed all registered callbacks are called with new name parameter. How do you write this code in dart? Thanks

ondrej
  • 967
  • 7
  • 26

1 Answers1

3

If it is a custom event

elem.on['name-changed'].listen((e) {
  // handle event
});

if it is a DOM event there are usually specific getters like

elem.onNameChanged.listen((e) {
  // handle event
});

// or

elem.onNameChanged.listen((e) =>  /* handle event (inline function body) */);

You can also pass a method

elem.onNameChanged.listen(nameChangeHandler);

void nameChangeHandler(e) {
  // handle event
}

When you want to unsubscribe explicitely (not depend on garbage collection)

import 'dart:async';
StreamSubscription nameChangeSubscr;

nameChangeSubscr = elem.onnameChanged.listen((e) => /* handle event */);

// unsubscribe
if(nameChangeSubscr != null) nameChangeSubscr.cancel();

If you want a getter for custom events like DOM events have How do I fire a custom event from Polymer Dart?

update

maybe this is what you want

import 'dart:async';

class Person {
  Stream onNameChange;
  //StreamController _controller = new StreamController();
  StreamController _controller = new StreamController.broadcast();
  Person() {
    onNameChange = _controller.stream;
  }

  String _name;
  String get name => _name;
  set name(String val) {
    _name = val;
    _controller.add(val);
  }
}

void main() {
  var p = new Person();
  StreamSubscriptions nameChangeSubscr = p.onNameChange.listen((e) => print('name changed: $e'));


  var i = 0;
  new Timer.periodic(new Duration(milliseconds: 300), (Timer t) {
    if(i > 5) {
      t.cancel();
      if(nameChangeSubscr != 0) nameChangeSubscr.cancel();
    }
    p.name = "name ${i++}";
  });
}
Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I don't get it. Where is my Person class? What's elem? My Person class doesn’t have any on, onNameChanged methods yet. I don't know how to implement them. – ondrej Jul 23 '14 at 16:05
  • Sorry, I'm not very fluent in JavaScript and saved the time to investigate thoroughly. I'll extend my answer – Günter Zöchbauer Jul 23 '14 at 16:08
  • Do you really want to register callback this way or do you just need a method to get notified about changes like shown here http://stackoverflow.com/questions/24276737 – Günter Zöchbauer Jul 23 '14 at 16:14
  • This works, but not as expected. Scenario: Change name, then subscribe, then again change name => should call callback once, but it actually calls it twice. – ondrej Jul 23 '14 at 16:45
  • 1
    You are right, the previous version buffers events and sends them when a listener subscribes. The current version doesn't do this anymore. – Günter Zöchbauer Jul 23 '14 at 16:52