I solved it similarly:
I created a method "tfield" on top of the "field" method that takes an additional name of a tab the field is associated with. If there is none the tab is called "default" and the tab control is not rendered. In addition that field method can now do my FieldBinding and also the FieldTransform I need for the errors to be properly shown in the Bootstrap markup
The tfield method adds my field to a list of tab->field associations which I use later on to render the markup.
Then I override the defaultXml() method of the LiftScreen, injecting the markup from some central place and do some processing of the markup, specifically rendering the bindings to the fields as shown in your "CustomBindingLiftScreen".
Now a binding for some of the fields looks like this:
tfield("Person", "input-mini", screenVar.is.number)
tfield("Person", screenVar.is.lastname)
tfield("Address", screenVar.is.street)
tfield("Address", screenVar.is.city)
(I added a variation to tfield to be able to pass custom css classes to the field form.)
That's what tfield looks like:
protected def tfield[T](tabName: String, cssCls: String, underlying: => BaseField {type ValueType = T},
stuff: FilterOrValidate[T]*)(implicit man: Manifest[T]): Field {type ValueType = T} = {
val addedStuff: List[FilterOrValidate[T]] = FieldBinding(
underlying.name) :: stuff.toList
lazy val f: Field {type ValueType = T} = field[T](underlying, (flagFieldError(f, cssCls) :: addedStuff):_*)(man)
// add field to screenTabs list
f
}
The field has to be created with lazy val in order to use the value recursively inside the flagFieldError method, otherwise the compiler complains.
That approach seems to work reasonable well, and it's based on all your cool suggestions :)
Thanks,
Torsten.