I have following components:
class ChildModel:ViewModel() { //or it may be an POJO, it does not matter
val value ....
}
class ParentView: View() {
...
//Maybe this should be implemented into ParentViewModel
val childrenList:List<ChildModel>
fun addFragmentAsChild() {
//should:
// 1. display fragment within ParentView
// 2. add fragment into modelList (or fragmentList - it does not matter - important to have access to the model of every child )
}
fun deleteFragmentAsChild() {
//should destroy child and remove item from childrenList
//should work also on manual closing
}
}
class ChildFragment: Fragment() {
val model = ChildModel()
...
}
Summary: I want to create MDI and have access to model for every child.
I try do this with help "openInternalWindow" , but i can't create multiple child instances and i must manually manage the list - it's bad.
class InstrumentsView: View() {
override val root = BorderPane()
val instrumentList = ArrayList<InstrumentFragment>()
init {
with(root){
top = menubar {
menu("Tools") {
menuitem("Add instrument", "Shortcut+A") {
val newFragment = InstrumentFragment()
instrumentList.add(newFragment)
println(instrumentList.size)
openInternalWindow(newFragment, modal = false)
}
}
}
}
}
}
How to do it right tornadofx way?
In this example I'll use a view model and scoping to keep track of the item for each instrument editor. We need to make sure the instruments are unique so we can remove them from the list when the editor is closed. I created an
Instrument
domain object with an id and a name:We want a view model we can inject in the instrument editor. We'll make sure the view model contains a new instrument by default. It contains a facade for the name property so we can bind it to an editor input field.
A
Fragment
has callbacks foronDock
andonUndock
which can be used to keep track of the model for that fragment. We can use events to signal this. Declare the following events:Override the docking callbacks in
InstrumentFragment
to fire these events:For now we'll keep the list of instruments in the main view,
InstrumentsView
. This could just as well be in aController
.In the init class of the main view, we'll subscribe to the events we created and modify our list:
The "New Instrument" action will open a new InstrumentEditor in a new
Scope
so we can inject the view model into it and get an instance unique to that editor.Unfortunately, we can't use
openInternalWindow
as it currently only supports one internal window at a time. Therefore I usedopenWindow
instead.If you want to close the editor from an action, you can call
closeModal()
from anywhere inside the fragment.I've included a complete example app with a TableView that shows the currently open instruments. It will look like the image below. Notice that you need to hit save before the changes are flushed from the model and visible in the table.
I hope this is what you're looking for, or that you at least can modify it to fit your use case based on this sample.