Views
8 months ago

tornadofx-guide

11. Editing Models and

11. Editing Models and Validation You can check if a specific property is dirty, meaning that it has been changed compared to the backing source object value. val nameWasChanged = model.isDirty(model.name) There is also an extension property version that accomplishes the same task: val nameWasChanged = model.name.isDirty The shorthand version is an extension val on Property but it will only work for properties that are bound inside a ViewModel . You will find model.isNotDirty properties as well. If you need to dynamically react based on the dirty state of a specific property in the ViewModel , you can get a hold of a BooleanBinding representing the dirty state of that field like this: val nameDirtyProperty = model.dirtyStateFor(PersonModel::name) Extracting the Source Object Value To retrieve the backing object value for a property you can call model.backingValue(property) . val person = model.backingValue(property) Supporting Objects that Do Not Expose JavaFX Properties You probably wondered how to deal with domain objects that do not use JavaFX properties. Maybe you have a simple POJO with getters and setters, or normal kotlin var type properties. Since ViewModel requires JavaFX properties, TornadoFX comes with powerful wrappers that can turn any type of property into an observable JavaFX property. Here are some examples: 160

11. Editing Models and Validation // Java POJO getter/setter property class JavaPersonViewModel(person: JavaPerson) : ViewModel() { val name = bind { person.observable(JavaPerson::getName, JavaPerson::setName) } } // Kotlin var property class PersonVarViewModel(person: Person) : ViewModel() { val name = bind { person.observable(Person::name) } } As you can see, it is easy to convert any property type to an observable property. Specific Property Subtypes (IntegerProperty, BooleanProperty) If you bind, for example, an IntegerProperty , the type of the facade property will look like Property but it is infact an IntegerProperty under the hood. If you need to access the special functions provided by IntegerProperty , you will have to cast the bind result: val age = bind(Person::ageProperty) as IntegerProperty Similarily, you can expose a read only property by specifying a read only type: val age = bind(Person::ageProperty) as ReadOnlyIntegerProperty The reason for this is an unfortunate shortcoming on the type system that prevents the compiler from differentiating between overloaded bind functions for these specific types, so the single bind function inside ViewModel inspects the property type and returns the best match, but unfortunately the return type signature has to be Property for now. Rebinding As you saw in the TableView example above, it is possible to change the domain object that is wrapped by the ViewModel . This test case sheds some more light on that: 161

GUIDE
GUIDE
GUIDE
Guide
Guide
GUIDE
GUIDE
GUIDE
Guide
GUIDE
Guide
GUIDE
Guide
GUIDE
GUIDE