おじゃまぷよ系エンジニアメモ

アプリエンジニアからサーバーとインフラエンジニアに転身しました

kotlinのjavascirptで非同期で取得したデータをDOMにバインドするサンプル

kotlinがAndroidに公式サポートされて盛り上がっておりますね。
一応Androidエンジニアやっている?いた?のでkotlinは少し追っていたのですが、今ではWebエンジニアとしての方が強くなってきたので
あえてkotlinでjavascriptやってみよう思い立ってDelegate.Observableを使って、非同期で取得したデータをhtmlのDOMにバインドできないかなぁと思ってやってみたら楽しくなってきたのでメモ

kotlinでjavascriptの準備

チュートリアルにそって準備しました kotlinlang.org

適当にhtmlを用意

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="../kjs/out/production/kjs/lib/kotlin.js"></script>
    <script src="../kjs/out/production/kjs/kjs.js"></script>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <input id="sampleText" type="text" value="text" title="sampleText">
    <input id="sampleCheckBox" type="checkbox" title="checkBox">
    <button id="sampleButton">sampleButton</button>
</div>
<script>
    new kjs.SampleRequest().request();
</script>
</body>
</html>

divタグの中のDOMのvalueやらcheckboxのdisableの切り替えをAPIを叩いて帰ってきたJSONレスポンスをdata classに変換してバインドする
みたいなものを想定しています。無邪気にid指定しているのは許してください。nameでもclassでも取得できるのでそこは後でお好みで変換してください。 scriptタグ内のkjs.SampleRequest().request()で非同期でGETリクエストを投げてJSONを受けってデータバインドします

バインドするdata class

data class SampleEntity(val inputText: String, val disabled: Boolean, val buttonText: String)

inputTextをDOMのtextのvalueに
buttonTextをDOMのButtonのtextContentに
disableをcheckBoxのdisableに バインドする想定のdata class

バインドするDOMのテンプレートクラス

object SampleTemplate {
    var entity by Delegates.observable<SampleEntity?>(null) {
        _, _, new ->
        new?.let {
            inputText.value = new.inputText
            checkBox.disabled = new.disabled
            button.textContent = new.buttonText
        }
    }
    val inputText: HTMLInputElement = document.getElementById("sampleText") as HTMLInputElement
    val checkBox: HTMLInputElement = document.getElementById("sampleCheckBox") as HTMLInputElement
    val button: HTMLButtonElement = document.getElementById("sampleButton") as HTMLButtonElement
}

それぞれのDOMの情報をメンバ変数に持って
Delegate.observableを利用してSampleEntityがsetされたらDOMに値を入れるようにしています

GETのRequestを投げるクラス

class SampleRequest {
    fun request(){
        val req = XMLHttpRequest()
        req.onloadend = fun(event:Event){
            SampleTemplate.entity = JSON.parse<SampleEntity>(req.responseText)
        }
        req.open("GET","http://localhost:63342/kjs/json_text.txt",true)
        req.send()
    }
}

XMLHttpRequestで非同期でGETリクエストを投げて、取得したJSONをSampleEntityに変換してSampleTemplateのentityにセットしています。

適当なJSONのファイル用意します

{"inputText":"テキストはいる","disabled":true,"buttonText":"hoge"}

buildしてブラウザでチェックします

ディレクトリ構成はこんな感じですごく適当においてます f:id:masahide318:20170606235740p:plain

IntelliJからindex.htmlをopenすると「http://localhost:63342/kjs/index.html」みたいなURLで開きます

すると
f:id:masahide318:20170606234207p:plain
から
f:id:masahide318:20170606234312p:plain

にtextの内容やcheckboxがdisable状態になったりと、データが反映されます。
今回は恐らく最小の構成?でバーっと書いてみましたが、案外使えそうな気がしています。

おまけ

f:id:masahide318:20170606235313p:plain

チュートリアルにあるようにdebugの設定をすると、kotlinのソース上でちゃんとブレイクポイント貼れるのでかなりデバッグが助かります。 vue.jsやほかのjsのライブラリとうまく組み合わせたパターンなど色々と試してみたいですね。