{"action":"created","issue":{"url":"https://api.github.com/repos/thomasnield/RxKotlinFX/issues/8","repository_url":"https://api.github.com/repos/thomasnield/RxKotlinFX","labels_url":"https://api.github.com/repos/thomasnield/RxKotlinFX/issues/8/labels{/name}","comments_url":"https://api.github.com/repos/thomasnield/RxKotlinFX/issues/8/comments","events_url":"https://api.github.com/repos/thomasnield/RxKotlinFX/issues/8/events","html_url":"https://github.com/thomasnield/RxKotlinFX/issues/8","id":163310534,"number":8,"title":"Reactive Dialogs","user":{"login":"thomasnield","id":7420801,"avatar_url":"https://avatars.githubusercontent.com/u/7420801?v=3","gravatar_id":"","url":"https://api.github.com/users/thomasnield","html_url":"https://github.com/thomasnield","followers_url":"https://api.github.com/users/thomasnield/followers","following_url":"https://api.github.com/users/thomasnield/following{/other_user}","gists_url":"https://api.github.com/users/thomasnield/gists{/gist_id}","starred_url":"https://api.github.com/users/thomasnield/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thomasnield/subscriptions","organizations_url":"https://api.github.com/users/thomasnield/orgs","repos_url":"https://api.github.com/users/thomasnield/repos","events_url":"https://api.github.com/users/thomasnield/events{/privacy}","received_events_url":"https://api.github.com/users/thomasnield/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2016-07-01T03:06:27Z","updated_at":"2016-07-14T01:04:24Z","closed_at":null,"body":"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. \r\n\r\nBut I found an interesting pattern that seems to work consistently: Make the dialog return an `Observable` of the result. Note I am using [TornadoFX](https://github.com/edvin/tornadofx) in this example. \r\n\r\n```kotlin\r\nclass YesNoConfirmDialog(val message: String) : Fragment() {\r\n    override val root = BorderPane()\r\n    var result: Observable<Response> by singleAssign()\r\n    init {\r\n        with(root) {\r\n            top {\r\n                label(message)\r\n            }\r\n            center {\r\n                hbox {\r\n                    alignment = Pos.BASELINE_CENTER\r\n                    result = Observable.concat(\r\n                            button(\"YES\").actionEvents().map { Response.YES },\r\n                            button(\"NO\").actionEvents().map { Response.NO }\r\n                    ).take(1).doOnCompleted { this@YesNoConfirmDialog.closeModal() }\r\n                }\r\n            }\r\n        }\r\n        openModal()\r\n    }\r\n    enum class Response { YES, NO }\r\n}\r\n```\r\n\r\nThen all I have to do is `flatMap()` to this dialog's `result` property which will emit as an `Observable<Response>`. \r\n\r\n```kotlin\r\nsourceObservable\r\n    .flatMap { YesNoConfirmDialog(\"Are you sure you want item $it to be committed?\").result }\r\n    .subscribe { println(\"You selected $it\") }\r\n```\r\n\r\n![](http://i.imgur.com/J9pJxEk.png)\r\n\r\nI would hate to build dialogs from scratch like I did above. It would be ideal to put extension functions on existing [JavaFX dialogs](http://code.makery.ch/blog/javafx-8-dialogs/) that return the `Observable`. This may be worth exploring. \r\n\r\nIt might be even better to create simple functions that take care of creating and returning the result of dialogs. \r\n\r\n```kotlin\r\nsourceObservable\r\n    .flatMap { yesNoConfirmDialog(\"Are you sure you want item $it to be committed?\") }\r\n    .subscribe { println(\"You selected $it\") }\r\n```"},"comment":{"url":"https://api.github.com/repos/thomasnield/RxKotlinFX/issues/comments/232529648","html_url":"https://github.com/thomasnield/RxKotlinFX/issues/8#issuecomment-232529648","issue_url":"https://api.github.com/repos/thomasnield/RxKotlinFX/issues/8","id":232529648,"user":{"login":"thomasnield","id":7420801,"avatar_url":"https://avatars.githubusercontent.com/u/7420801?v=3","gravatar_id":"","url":"https://api.github.com/users/thomasnield","html_url":"https://github.com/thomasnield","followers_url":"https://api.github.com/users/thomasnield/followers","following_url":"https://api.github.com/users/thomasnield/following{/other_user}","gists_url":"https://api.github.com/users/thomasnield/gists{/gist_id}","starred_url":"https://api.github.com/users/thomasnield/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thomasnield/subscriptions","organizations_url":"https://api.github.com/users/thomasnield/orgs","repos_url":"https://api.github.com/users/thomasnield/repos","events_url":"https://api.github.com/users/thomasnield/events{/privacy}","received_events_url":"https://api.github.com/users/thomasnield/received_events","type":"User","site_admin":false},"created_at":"2016-07-14T01:04:24Z","updated_at":"2016-07-14T01:04:24Z","body":"Okay I think I'm letting the scope run away from me. I'm just going to implement the following extensions and keep it simple. Maybe I'll include an `Optional<T>.toObservable()` as well. \r\n\r\nSometimes I forget Kotlin allows you to create your own DSL's. If you want to create a `confirmDialog()` function then the language is small enough to make that trivial. No need to centralize those in an API.\r\n\r\n```kotlin\r\nfun <T> Dialog<T>.toObservable() = fromDialogSource(this)\r\n\r\nfun <T> Optional<T>.toObservable() = Observable.just(this)\r\n        .filter { it.isPresent }\r\n        .map { it.get() }\r\n```"}}
{"actor":{"display_login":"thomasnield"}}