@singuerinc

2011-06-14

as3-signals + binding

actionscript3, as3-signals, binding

Estoy trabajando en un proyecto donde necesito actualizar la vista constantemente con información del modelo. En Flex esto es relativamente fácil mediante la etiqueta [Bindable], pero en un proyeto puramente as3 no lo es tanto.

Aquí es donde as3-signals nos puede dar una mano, si sois como yo, que ando buscando siempre código nuevo que me facilite la vida habréis notado que existe un branch en as3-signals de Robert Penner llamado "binding".

Es un set de classes que nos permiten vincular una propiedad de un objeto a otra propiedad de otro objecto. Me explico: por ejemplo, cada vez que actualizo la propiedad "name" del objeto User quiero que se actualice la propiedad "text" de un "TextField".

Para hacer esto necesitamos que nuestro objeto User implemente la interface IBindable que se encuentra dentro del paquete de as3-signals, entonces tendremos una nueva propiedad dentro de User llamada changeSignal que será la encargada de notificar sobre los cambios en el objeto. Veamos un poco el código, la classe User nos quedaría así:

package net.singuerinc.labs.signals.binding {
  import org.osflash.signals.binding.ChangeSignal;
  import org.osflash.signals.binding.IBindable;
  import org.osflash.signals.binding.IChangeSignal;

  public class User implements IBindable {

    private var _name:String;
    private var _changeSignal:ChangeSignal;

    public function User() {
    }

    public function set name(value:String):void {
      _name = value;
      changeSignal.dispatch('name', _name);
    }

    public function get name():String {
      return _name;
    }

    public function get changeSignal():IChangeSignal {
      return _changeSignal ||= new ChangeSignal(this);
    }
  }
}

Ahora, para vincular el TextField con User necesitamos de Binder, esta vinculará los dos objetos:

package net.singuerinc.labs.signals.binding {
  import com.bit101.components.PushButton;
  import org.osflash.signals.binding.Binder;
  import flash.display.Sprite;
  import flash.events.MouseEvent;
  import flash.text.TextField;
  import flash.text.TextFieldAutoSize;

  public class SignalsBindingExample extends [Sprite][4] {

    public var user:User;

    public function SignalsBindingExample() {

      new PushButton(this, , 20, 'change user name', onClick);

      var txt1:TextField = new TextField();
      txt1.autoSize = TextFieldAutoSize.LEFT;
      addChild(txt1);

      user = new User();
      user.name = 'User1';

      var binder:Binder = new Binder();
      binder.bind(txt1, 'text', user, 'name');
    }

    private function onClick(event:MouseEvent):void {
      user.name = 'User' + Math.random();
    }
  }
}

Listo, ahora cada vez que hagamos actualicemos user.name automáticamente Binder hará que ese valor se refleje en el TextField! Source