One of the pain points I've had with Rx and JavaFX is putting a dialog somewhere in the middle of an Observable chain, usually to prevent emissions from going forward on some condition. It's messy and maybe I'm just not competent enough with maintaining modality, and I struggle to get it right.
But I found an interesting pattern that seems to work consistently: Make the dialog return an Observable of the result. Note I am using TornadoFX in this example.
class YesNoConfirmDialog(val message: String) : Fragment() {
override val root = BorderPane()
var result: Observable<Response> by singleAssign()
init {
with(root) {
top {
label(message)
}
center {
hbox {
alignment = Pos.BASELINE_CENTER
result = Observable.concat(
button("YES").actionEvents().map { Response.YES },
button("NO").actionEvents().map { Response.NO }
).take(1).doOnCompleted { this@YesNoConfirmDialog.closeModal() }
}
}
}
openModal()
}
enum class Response { YES, NO }
}
Then all I have to do is flatMap() to this dialog's result property which will emit as an Observable<Response>.
sourceObservable
.flatMap { YesNoConfirmDialog("Are you sure you want item $it to be committed?").result }
.subscribe { println("You selected $it") }

I would hate to build dialogs from scratch like I did above. It would be ideal to put extension functions on existing JavaFX dialogs that return the Observable. This may be worth exploring.
It might be even better to create simple functions that take care of creating and returning the result of dialogs.
sourceObservable
.flatMap { yesNoConfirmDialog("Are you sure you want item $it to be committed?") }
.subscribe { println("You selected $it") }
One of the pain points I've had with Rx and JavaFX is putting a dialog somewhere in the middle of an
Observablechain, usually to prevent emissions from going forward on some condition. It's messy and maybe I'm just not competent enough with maintaining modality, and I struggle to get it right.But I found an interesting pattern that seems to work consistently: Make the dialog return an
Observableof the result. Note I am using TornadoFX in this example.Then all I have to do is
flatMap()to this dialog'sresultproperty which will emit as anObservable<Response>.sourceObservable .flatMap { YesNoConfirmDialog("Are you sure you want item $it to be committed?").result } .subscribe { println("You selected $it") }I would hate to build dialogs from scratch like I did above. It would be ideal to put extension functions on existing JavaFX dialogs that return the
Observable. This may be worth exploring.It might be even better to create simple functions that take care of creating and returning the result of dialogs.
sourceObservable .flatMap { yesNoConfirmDialog("Are you sure you want item $it to be committed?") } .subscribe { println("You selected $it") }