Tornadofx Javafx – Cómo volver a cargar una vista / componente

Entonces es una pregunta básica.
Lo que bash lograr son vistas refrescantes desde otros puntos de vista.

Digamos que tengo una vista EmployeeTableView que muestra una representación tabular de los empleados haciendo una llamada a la API REST.
En otra vista, tengo un filter EmployeeFilterView en el que tengo género, range de salario, tipo de empleado, etc.
También tengo un object userContext en el que almaceno las preferences del usuario. Entonces, de forma pnetworkingeterminada, digamos que he almacenado el valor del filter de género para que sea masculino, el range de salario sea TODO, etc. Este object se envía como parámetro a EmployeeTableView.

Cuando se carga EmployeeTableView, realizo una llamada restAPI con los valores de userContext para get los detalles del empleado. Entonces eso funciona bien Ahora cambio el filter de género a Mujer y le asigno este valor en mi userContext.
Ahora bien, si pudiera volver a cargar EmployeeTableView con el object userContext, la llamada restapi obtendría los valores actualizados.

¿Pero cómo puedo hacer eso?
También sugiera un mejor enfoque si tiene.

EventBus es una solución válida para esto. Otro sería usar un ViewModel o Controller como el object UserContext y dejar que incluya la list real de empleados observables y luego vincular esa list a TableView en EmployeeTableView . Siempre que se actualice la list en el context, TableView se actualizará también.

La vista de filter llamaría a una function en el UserContext para realizar la llamada REST real y actualizar la list de empleados en function de eso.

Puede crear un object EmployeeQuery separado que se pueda inyectar en EmployeeFilterView y UserContext para que pueda extraer los valores de filter seleccionados para realizar la consulta. Este object de consulta contiene una list de todos los parameters de búsqueda que desea pasar al server.

También podría considerar crear un scope separado para mantener estos componentes separados si eso tiene sentido para su architecture.

Exactamente cómo se definen estos componentes son principalmente una cuestión de gusto, aquí hay una sugerencia. Utilicé el RangeSlider de ControlsFX para la interfaz de usuario de búsqueda simulada.

Para que sea más fácil imaginar cómo se relaciona esto, aquí hay una captura de pantalla:

(Todos los nombres y salarios son ficción 🙂

Aplicación del empleado

 /** * The employee domain model, implementing JsonModel so it can be fetched * via the REST API */ class Employee : JsonModel { val nameProperty = SimpleStringProperty() var name by nameProperty val salaryProperty = SimpleIntegerProperty() var salary by salaryProperty val genderProperty = SimpleObjectProperty<Gender>() var gender by genderProperty override fun updateModel(json: JsonObject) { with (json) { name = getString("name") salary = getInt("salary") gender = Gender.valueOf(getString("gender")) } } } enum class Gender { Male, Female } /** * Container for the list of employees as well as a search function called by the filter * view whenever it should update the employee list. */ class EmployeeContext : Controller() { val api: Rest by inject() val query: EmployeeQuery by inject() val employees = SimpleListProperty<Employee>() fun search() { runAsync { FXCollections.observableArrayList(Employee().apply { name = "Edvin Syse" gender = Gender.Male salary = 200_000 }) //api.post("employees/query", query).list().toModel<Employee>() } ui { employees.value = it } } } /** * Query object used to define the query sent to the server */ class EmployeeQuery : ViewModel(), JsonModel { val genderProperty = SimpleObjectProperty<Gender>(Gender.Female) var gender by genderProperty val salaryMinProperty = SimpleIntegerProperty(50_000) var salaryMin by salaryMinProperty val salaryMaxProperty = SimpleIntegerProperty(250_000) var salaryMax by salaryMaxProperty val salaryDescription = stringBinding(salaryMinProperty, salaryMaxProperty) { "$$salaryMin - $$salaryMax" } override fun toJSON(json: JsonBuilder) { with(json) { add("gender", gender.toString()) add("salaryMin", salaryMin) add("salaryMax", salaryMax) } } } /** * The search/filter UI */ class EmployeeFilterView : View() { val query: EmployeeQuery by inject() val context: EmployeeContext by inject() override val root = form { fieldset("Employee Filter") { field("Gender") { combobox(query.genderProperty, Gender.values().toList()) } field("Salary Range") { vbox { alignment = Pos.CENTER add(RangeSlider().apply { max = 500_000.0 lowValueProperty().bindBidirectional(query.salaryMinProperty) highValueProperty().bindBidirectional(query.salaryMaxProperty) }) label(query.salaryDescription) } } button("Search").action { context.search() } } } } /** * The UI that shows the search results */ class EmployeeTableView : View() { val context: EmployeeContext by inject() override val root = borderpane { center { tableview(context.employees) { column("Name", Employee::nameProperty) column("Gender", Employee::genderProperty) column("Salary", Employee::salaryProperty) } } } } /** * A sample view that ties the filter UI and result UI together */ class MainView : View("Employee App") { override val root = hbox { add(EmployeeFilterView::class) add(EmployeeTableView::class) } } 

Terminé usando Tornadofx -> EventBus

Básicamente, cuando cambio alguno de los filters, disparo un incluso que reconstruye el Nodo con los valores actualizados.

No estoy seguro de si el enfoque es correcto, es por eso que todavía lo mantengo abierto para discusión.

  • TornadoFX reemplaza el layoutChildren en la región
  • tornadofx EventBus expande la fila de la tabla usando el object tableview
  • Usar bibliotecas de UI de terceros con TornadoFX
  • Tornadofx tableview sincroniza dos tablas
  • ¿Cómo llenar el ancho de la tabla disponible con columnas?
  • TornadoFX: Type-Safe CSS con otras bibliotecas
  • Dibujando líneas desde ViewModel TornadoFX
  • ¿Por qué mi escena es nula?
  • Animación consecutiva en TornadoFX?
  • Crea una vista arbitraria
  • En TornadoFX, ¿cómo puedo separar layouts en diferentes classs y luego usarlos en el generador?