Views
2 months ago

tornadofx-guide

11. Editing Models and

11. Editing Models and Validation vable() var prevSelection: Person? = null init { with(root) { // TableView showing a list of people center { tableview(persons) { personTable = this column("Name", Person::nameProperty) column("Title", Person::titleProperty) } } // Edit the currently selected person selectionModel.selectedItemProperty().onChange { editPerson(it) prevSelection = it } } } right { form { fieldset("Edit person") { field("Name") { textfield() { nameField = this } } field("Title") { textfield() { titleField = this } } button("Save").action { save() } } } } private fun editPerson(person: Person?) { if (person != null) { prevSelection?.apply { nameProperty.unbindBidirectional(nameField.textProperty) titleProperty.unbindBidirectional(titleField.textProperty) } nameField.bind(person.nameProperty) titleField.bind(person.titleProperty) prevSelection = person } 154

11. Editing Models and Validation } private fun save() { // Extract the selected person from the tableView val person = personTable.selectedItem!! } } // A real application would persist the person here println("Saving ${person.name} / ${person.title}") We define a View consisting of a TableView in the center of a BorderPane and a Form on the right side. We define some properties for the form fields and the table itself so we can reference them later. While we build the table, we attach a listener to the selected item so we can call the editPerson function when the table selection changes. The editPerson function binds the properties of the selected person to the text fields in the form. Problems with our initial attempt At first glance it might look OK, but when we dig deeper there are several issues. Manual binding Every time the selection in the table changes, we have to unbind/rebind the data for the form fields manually. Apart from the added code and logic, there is another huge problem with this: the data is updated for every change in the text fields, and the changes will even be reflected in the table. While this might look cool and is technically correct, it presents one big problem: what if the user does not want to save the changes? We have no way of rolling back. So to prevent this, we would have to skip the binding altogether and manually extract the values from the text fields, then create a new Person object on save. In fact, this is a pattern found in many applications and expected by most users. Implementing a "Reset" button for this form would mean managing variables with the initial values and again assigning those values manually to the text fields. Tight Coupling Another issue is when it is time to save the edited person, the save function has to extract the selected item from the table again. For that to happen the save function has to know about the TableView . Alternatively it would have to know about the text fields like the editPerson function does, and manually extract the values to reconstruct a Person object. 155

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