Combining multiple read/write Binders

Viewed 68

I'm refactoring a view from using Binder.setBean(T) and mutable state to using pure views with Binder.readBean(T) and Binder.writeBean(T).

As part of the old view, I have several components with binders that don't bind directly to T but to its fields, and the components encapsulate and manage those fields entirely.

A simplified model:

class Foo {
  String name; // get, set
}

class Bar {
  int max; // get, set
  int min; // get, set
}

class Baz {
  Bar bar; // get only
  Foo foo; // get only
} 

And for the view code:

class FooEditor {
  Binder<Foo> binder;
  {
     binder.forField(...).bind(Foo::getName, Foo::setName);
  }
}

class BarEditor {
  Binder<Bar> binder;
  {
     binder.forField(...).bind(Bar::getMin, Foo::setMin);
     binder.forField(...).bind(Bar::getMax, Foo::setMax);
  }
}

class BazEditor {
  Binder<Baz> binder;
  {
    // old model:
    // binder.setBean(...);
    // fooEditor.getBinder().readBean(binder.getBean().getFoo());
    // barEditor.getBinder().readBean(binder.getBean().getBar());
  }
}

How can I achieve something like the following?

class BazEditor {
  {
    binder.forField(???)
        .bind(b -> fooEditor.getBinder().readBean(b.getFoo()),
              (b, v) -> fooEditor.getBinder().writeBean(b.getFoo()));
    // repeat for Bar
  }
}

I've tried using ReadOnlyHasValue, but I think due to its implementation, the "getter" always returns the same value (by instance equality), the field is never considered modified by the binder, and the setter is never called.

I've thought about refactoring the components Foo and Bar to bind directly to sub-properties given a Binder<Baz>, but I feel like there should be a better solution.

1 Answers

I think there there is no established best practice for this. I tend to prefer wrapping sub-form as a Field component whose value is Bean or list of Beans myself. I.e. full encapsulation of the internal logic of the sub-form. Then it is clear to use this sub-form as bound field in the Binder on the upper level (it does not need to know whether sub-form has a Binder used internally or not). You can find example of that approach (amongst some other things) in this example project

https://github.com/TatuLund/ProtoTools

Related